diff options
Diffstat (limited to 'torrus/bin')
30 files changed, 6232 insertions, 0 deletions
diff --git a/torrus/bin/Makefile.am b/torrus/bin/Makefile.am new file mode 100644 index 000000000..b6abf740d --- /dev/null +++ b/torrus/bin/Makefile.am @@ -0,0 +1,177 @@ + +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: Makefile.am,v 1.1 2010-12-27 00:04:01 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> +# + +SUBST = @abs_top_builddir@/setup_tools/substvars.sh + +pkgbindir = @pkgbindir@ +pkgbin_SCRIPTS = \ + acledit \ + action_notify \ + action_printemail \ + action_snmptrap \ + action_snmpv1trap \ + bdbinfo \ + buildsearchdb \ + cleanup \ + clearcache \ + collector \ + compilexml \ + configinfo \ + configsnapshot \ + devdiscover \ + flushmonitors \ + genddx \ + genlist \ + genreport \ + install_plugin \ + monitor \ + nodeid \ + rrddir2xml \ + schedulerinfo \ + snmpfailures \ + srvderive \ + torrus.fcgi \ + ttproclist + +wrapperdir = @wrapperdir@ +wrapper_SCRIPTS = \ + torrus + +CLEANFILES = $(pkgbin_SCRIPTS) $(wrapper_SCRIPTS) + +EXTRA_DIST = \ + acledit.in \ + action_notify.in \ + action_printemail.in \ + action_snmptrap.in \ + action_snmpv1trap.in \ + bdbinfo.in \ + buildsearchdb.in \ + clearcache.in \ + cleanup.in \ + collector.in \ + compilexml.in \ + configinfo.in \ + configsnapshot.in \ + devdiscover.in \ + flushmonitors.in \ + genddx.in \ + genlist.in \ + genreport.in \ + install_plugin.in \ + monitor.in \ + nodeid.in \ + rrddir2xml.in \ + schedulerinfo.in \ + snmpfailures.in \ + srvderive.in \ + torrus.fcgi.in \ + torrus.in \ + ttproclist.in + + +# Result of: +# ls -1 | egrep '^[a-z][^.]+$' | \ +# awk '{printf "%s: %s.in\n\t$(SUBST) %s.in > %s\n\n", $1, $1, $1, $1}' + +acledit: acledit.in + $(SUBST) acledit.in > acledit + +action_printemail: action_printemail.in + $(SUBST) action_printemail.in > action_printemail + +action_notify: action_notify.in + $(SUBST) action_notify.in > action_notify + +action_snmptrap: action_snmptrap.in + $(SUBST) action_snmptrap.in > action_snmptrap + +action_snmpv1trap: action_snmpv1trap.in + $(SUBST) action_snmpv1trap.in > action_snmpv1trap + +buildsearchdb: buildsearchdb.in + $(SUBST) buildsearchdb.in > buildsearchdb + +bdbinfo: bdbinfo.in + $(SUBST) bdbinfo.in > bdbinfo + +cleanup: cleanup.in + $(SUBST) cleanup.in > cleanup + +clearcache: clearcache.in + $(SUBST) clearcache.in > clearcache + +collector: collector.in + $(SUBST) collector.in > collector + +compilexml: compilexml.in + $(SUBST) compilexml.in > compilexml + +configinfo: configinfo.in + $(SUBST) configinfo.in > configinfo + +configsnapshot: configsnapshot.in + $(SUBST) configsnapshot.in > configsnapshot + +devdiscover: devdiscover.in + $(SUBST) devdiscover.in > devdiscover + +flushmonitors: flushmonitors.in + $(SUBST) flushmonitors.in > flushmonitors + +genddx: genddx.in + $(SUBST) genddx.in > genddx + +genlist: genlist.in + $(SUBST) genlist.in > genlist + +genreport: genreport.in + $(SUBST) genreport.in > genreport + +install_plugin: install_plugin.in + $(SUBST) install_plugin.in > install_plugin + +monitor: monitor.in + $(SUBST) monitor.in > monitor + +nodeid: nodeid.in + $(SUBST) nodeid.in > nodeid + +rrddir2xml: rrddir2xml.in + $(SUBST) rrddir2xml.in > rrddir2xml + +schedulerinfo: schedulerinfo.in + $(SUBST) schedulerinfo.in > schedulerinfo + +snmpfailures: snmpfailures.in + $(SUBST) snmpfailures.in > snmpfailures + +srvderive: srvderive.in + $(SUBST) srvderive.in > srvderive + +torrus: torrus.in + $(SUBST) torrus.in > torrus + +torrus.fcgi: torrus.fcgi.in + $(SUBST) torrus.fcgi.in > torrus.fcgi + +ttproclist: ttproclist.in + $(SUBST) ttproclist.in > ttproclist diff --git a/torrus/bin/Makefile.in b/torrus/bin/Makefile.in new file mode 100644 index 000000000..fb4aa2bfb --- /dev/null +++ b/torrus/bin/Makefile.in @@ -0,0 +1,538 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: Makefile.in,v 1.1 2010-12-27 00:04:01 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> +# + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = bin +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(pkgbindir)" "$(DESTDIR)$(wrapperdir)" +pkgbinSCRIPT_INSTALL = $(INSTALL_SCRIPT) +wrapperSCRIPT_INSTALL = $(INSTALL_SCRIPT) +SCRIPTS = $(pkgbin_SCRIPTS) $(wrapper_SCRIPTS) +SOURCES = +DIST_SOURCES = +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +FIND = @FIND@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KILL = @KILL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERLINC = @PERLINC@ +POD2MAN = @POD2MAN@ +POD2MAN_PRESENT_FALSE = @POD2MAN_PRESENT_FALSE@ +POD2MAN_PRESENT_TRUE = @POD2MAN_PRESENT_TRUE@ +POD2TEXT = @POD2TEXT@ +POD2TEXT_PRESENT_FALSE = @POD2TEXT_PRESENT_FALSE@ +POD2TEXT_PRESENT_TRUE = @POD2TEXT_PRESENT_TRUE@ +RM = @RM@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SLEEP = @SLEEP@ +STRIP = @STRIP@ +SU = @SU@ +VERSION = @VERSION@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +cachedir = @cachedir@ +cfgdefdir = @cfgdefdir@ +datadir = @datadir@ +dbhome = @dbhome@ +defrrddir = @defrrddir@ +distxmldir = @distxmldir@ +enable_pkgonly = @enable_pkgonly@ +enable_varperm = @enable_varperm@ +exec_prefix = @exec_prefix@ +exmpdir = @exmpdir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +logdir = @logdir@ +mandir = @mandir@ +mansec_misc = @mansec_misc@ +mansec_usercmd = @mansec_usercmd@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +perlithreads = @perlithreads@ +perllibdir = @perllibdir@ +perllibdirs = @perllibdirs@ +piddir = @piddir@ +pkgbindir = @pkgbindir@ +pkgdocdir = @pkgdocdir@ +pkghome = @pkghome@ +plugdevdisccfgdir = @plugdevdisccfgdir@ +pluginsdir = @pluginsdir@ +plugtorruscfgdir = @plugtorruscfgdir@ +plugwrapperdir = @plugwrapperdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +reportsdir = @reportsdir@ +sbindir = @sbindir@ +scriptsdir = @scriptsdir@ +seslockdir = @seslockdir@ +sesstordir = @sesstordir@ +sharedstatedir = @sharedstatedir@ +siteconfdir = @siteconfdir@ +sitedir = @sitedir@ +sitexmldir = @sitexmldir@ +supdir = @supdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +tmpldir = @tmpldir@ +tmpluserdir = @tmpluserdir@ +torrus_user = @torrus_user@ +var_group = @var_group@ +var_mode = @var_mode@ +var_user = @var_user@ +varprefix = @varprefix@ +webplaindir = @webplaindir@ +webscriptsdir = @webscriptsdir@ +wrapperdir = @wrapperdir@ +SUBST = @abs_top_builddir@/setup_tools/substvars.sh +pkgbin_SCRIPTS = \ + acledit \ + action_notify \ + action_printemail \ + action_snmptrap \ + action_snmpv1trap \ + bdbinfo \ + buildsearchdb \ + cleanup \ + clearcache \ + collector \ + compilexml \ + configinfo \ + configsnapshot \ + devdiscover \ + flushmonitors \ + genddx \ + genlist \ + genreport \ + install_plugin \ + monitor \ + nodeid \ + rrddir2xml \ + schedulerinfo \ + snmpfailures \ + srvderive \ + torrus.fcgi \ + ttproclist + +wrapper_SCRIPTS = \ + torrus + +CLEANFILES = $(pkgbin_SCRIPTS) $(wrapper_SCRIPTS) +EXTRA_DIST = \ + acledit.in \ + action_notify.in \ + action_printemail.in \ + action_snmptrap.in \ + action_snmpv1trap.in \ + bdbinfo.in \ + buildsearchdb.in \ + clearcache.in \ + cleanup.in \ + collector.in \ + compilexml.in \ + configinfo.in \ + configsnapshot.in \ + devdiscover.in \ + flushmonitors.in \ + genddx.in \ + genlist.in \ + genreport.in \ + install_plugin.in \ + monitor.in \ + nodeid.in \ + rrddir2xml.in \ + schedulerinfo.in \ + snmpfailures.in \ + srvderive.in \ + torrus.fcgi.in \ + torrus.in \ + ttproclist.in + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu bin/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu bin/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-pkgbinSCRIPTS: $(pkgbin_SCRIPTS) + @$(NORMAL_INSTALL) + test -z "$(pkgbindir)" || $(mkdir_p) "$(DESTDIR)$(pkgbindir)" + @list='$(pkgbin_SCRIPTS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f $$d$$p; then \ + f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \ + echo " $(pkgbinSCRIPT_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgbindir)/$$f'"; \ + $(pkgbinSCRIPT_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgbindir)/$$f"; \ + else :; fi; \ + done + +uninstall-pkgbinSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(pkgbin_SCRIPTS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \ + echo " rm -f '$(DESTDIR)$(pkgbindir)/$$f'"; \ + rm -f "$(DESTDIR)$(pkgbindir)/$$f"; \ + done +install-wrapperSCRIPTS: $(wrapper_SCRIPTS) + @$(NORMAL_INSTALL) + test -z "$(wrapperdir)" || $(mkdir_p) "$(DESTDIR)$(wrapperdir)" + @list='$(wrapper_SCRIPTS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f $$d$$p; then \ + f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \ + echo " $(wrapperSCRIPT_INSTALL) '$$d$$p' '$(DESTDIR)$(wrapperdir)/$$f'"; \ + $(wrapperSCRIPT_INSTALL) "$$d$$p" "$(DESTDIR)$(wrapperdir)/$$f"; \ + else :; fi; \ + done + +uninstall-wrapperSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(wrapper_SCRIPTS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \ + echo " rm -f '$(DESTDIR)$(wrapperdir)/$$f'"; \ + rm -f "$(DESTDIR)$(wrapperdir)/$$f"; \ + done +uninstall-info-am: +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(SCRIPTS) +installdirs: + for dir in "$(DESTDIR)$(pkgbindir)" "$(DESTDIR)$(wrapperdir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-pkgbinSCRIPTS install-wrapperSCRIPTS + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-pkgbinSCRIPTS \ + uninstall-wrapperSCRIPTS + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-pkgbinSCRIPTS install-strip install-wrapperSCRIPTS \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-info-am \ + uninstall-pkgbinSCRIPTS uninstall-wrapperSCRIPTS + + +# Result of: +# ls -1 | egrep '^[a-z][^.]+$' | \ +# awk '{printf "%s: %s.in\n\t$(SUBST) %s.in > %s\n\n", $1, $1, $1, $1}' + +acledit: acledit.in + $(SUBST) acledit.in > acledit + +action_printemail: action_printemail.in + $(SUBST) action_printemail.in > action_printemail + +action_notify: action_notify.in + $(SUBST) action_notify.in > action_notify + +action_snmptrap: action_snmptrap.in + $(SUBST) action_snmptrap.in > action_snmptrap + +action_snmpv1trap: action_snmpv1trap.in + $(SUBST) action_snmpv1trap.in > action_snmpv1trap + +buildsearchdb: buildsearchdb.in + $(SUBST) buildsearchdb.in > buildsearchdb + +bdbinfo: bdbinfo.in + $(SUBST) bdbinfo.in > bdbinfo + +cleanup: cleanup.in + $(SUBST) cleanup.in > cleanup + +clearcache: clearcache.in + $(SUBST) clearcache.in > clearcache + +collector: collector.in + $(SUBST) collector.in > collector + +compilexml: compilexml.in + $(SUBST) compilexml.in > compilexml + +configinfo: configinfo.in + $(SUBST) configinfo.in > configinfo + +configsnapshot: configsnapshot.in + $(SUBST) configsnapshot.in > configsnapshot + +devdiscover: devdiscover.in + $(SUBST) devdiscover.in > devdiscover + +flushmonitors: flushmonitors.in + $(SUBST) flushmonitors.in > flushmonitors + +genddx: genddx.in + $(SUBST) genddx.in > genddx + +genlist: genlist.in + $(SUBST) genlist.in > genlist + +genreport: genreport.in + $(SUBST) genreport.in > genreport + +install_plugin: install_plugin.in + $(SUBST) install_plugin.in > install_plugin + +monitor: monitor.in + $(SUBST) monitor.in > monitor + +nodeid: nodeid.in + $(SUBST) nodeid.in > nodeid + +rrddir2xml: rrddir2xml.in + $(SUBST) rrddir2xml.in > rrddir2xml + +schedulerinfo: schedulerinfo.in + $(SUBST) schedulerinfo.in > schedulerinfo + +snmpfailures: snmpfailures.in + $(SUBST) snmpfailures.in > snmpfailures + +srvderive: srvderive.in + $(SUBST) srvderive.in > srvderive + +torrus: torrus.in + $(SUBST) torrus.in > torrus + +torrus.fcgi: torrus.fcgi.in + $(SUBST) torrus.fcgi.in > torrus.fcgi + +ttproclist: ttproclist.in + $(SUBST) ttproclist.in > ttproclist +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/torrus/bin/acledit.in b/torrus/bin/acledit.in new file mode 100644 index 000000000..725d3b5eb --- /dev/null +++ b/torrus/bin/acledit.in @@ -0,0 +1,432 @@ +#!@PERL@ +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: acledit.in,v 1.1 2010-12-27 00:04:01 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +BEGIN { require '@torrus_config_pl@'; } + +use strict; +use Getopt::Long; + +use Torrus::Log; +use Torrus::ACL::Edit; +use Torrus::SiteConfig; + +exit(1) if not Torrus::SiteConfig::verify(); + +our %knownPrivileges = + ( 'DisplayTree' => 'tree', + 'DisplayAdmInfo' => 'tree', + 'DisplayReports' => 'tree', + 'GlobalSearch' => 'global' ); + +our @addgroups; +our @delgroups; +our @modgroups; + +our @permitprivs; +our @denyprivs; +our @forobjects; + +our $adduser; +our $addhost; +our $deluser; +our $moduser; +our @addtogroups; +our @delfromgroups; +our $password; +our $host_password; +our $commonname; +our $exportfile; +our $exporttemplate = "aclexport.xml"; +our $importfile; +our $clearconf; + +our @showgroups; +our @showusers; +our $listall; + +our $force; +our $debug; +our $verbose; +our $help_needed; + +my $ok = GetOptions ('addgroup=s' => \@addgroups, + 'delgroup=s' => \@delgroups, + 'modgroup=s' => \@modgroups, + 'permit=s' => \@permitprivs, + 'deny=s' => \@denyprivs, + 'for=s' => \@forobjects, + 'adduser=s' => \$adduser, + 'addhost=s' => \$addhost, + 'deluser=s' => \$deluser, + 'moduser=s' => \$moduser, + 'addtogroup=s' => \@addtogroups, + 'delfromgroup=s' => \@delfromgroups, + 'password=s' => \$password, + 'hostpassword=s' => \$host_password, + 'cn=s' => \$commonname, + 'export=s' => \$exportfile, + 'template=s' => \$exporttemplate, + 'import=s' => \$importfile, + 'clear' => \$clearconf, + 'showgroup=s' => \@showgroups, + 'showuser=s' => \@showusers, + 'list' => \$listall, + 'force' => \$force, + 'debug' => \$debug, + 'verbose' => \$verbose, + 'help' => \$help_needed); + +if( not $ok or $help_needed or scalar(@ARGV) > 0 or + ( @addgroups ? 1:0 ) + ( @delgroups ? 1:0 ) + ( @modgroups ? 1:0 ) > 1 or + ( ( @permitprivs or @denyprivs ) and not @forobjects ) or + ( $adduser ? 1:0 ) + ( $deluser ? 1:0 ) + ( $moduser ? 1:0 ) > 1 or + ( ( @addtogroups or @delfromgroups or + length($password) > 0 or + length($host_password) > 0 or + length($commonname) > 0 ) and + ( length($adduser) + length($addhost) + length($moduser) == 0 ) ) ) +{ + print STDERR "Usage: $0 [options...]\n", + "Group Options:\n", + " --addgroup=GROUP add group\n", + " --delgroup=GROUP delete group\n", + " --modgroup=GROUP modify group\n", + " --permit=PRIVILEGE add privilege to group(s)\n", + " --deny=PRIVILEGE revoke privilege from group(s)\n", + " --for=TREE subject of privilege or '*'\n", + " --force change privilege for non-existent object\n", + " --showgroup=GROUP display group details\n", + "User Options:\n", + " --adduser=UID add new user\n", + " --deluser=UID delete user\n", + " --moduser=UID modify user\n", + " --addtogroup=GROUP add user to group(s)\n", + " --delfromgroup=GROUP delete user from group(s)\n", + " --password=PASSWORD set the user password\n", + " --hostpassword=PASSWORD set the host password (UID must be a host)\n", + " --cn=\"John Smith\" set the user common name\n", + " --showuser=USER display user details\n", + "General Options:\n", + " --export=FILE export ACL config to a file\n", + " --template=NAME [aclexport.xml] export template \n", + " --import=FILE import ACL config from a file\n", + " --clear delete ALL user and privileges configuration\n", + " --list list all users and groups they belong to\n", + " --debug set the log level to debug\n", + " --verbose set the log level to verbose\n", + " --help this help message\n\n", + "Privileges:\n", + " DisplayTree see the datasources for a tree\n", + " DisplayAdmInfo see the administrative info for a tree\n", + " DisplayReports see the administrative info for a tree\n", + " GlobalSearch search globally for '*'\n"; + exit 1; +} + +if( $debug ) +{ + Torrus::Log::setLevel('debug'); +} +elsif( $verbose ) +{ + Torrus::Log::setLevel('verbose'); +} + +# We set the signal handlers, but we actually don't react on +# signals, because the acledit is a fast utility +&Torrus::DB::setSafeSignalHandlers(); + +Verbose(sprintf("Torrus version %s", '@VERSION@')); + +my $aclEdit = new Torrus::ACL::Edit; + +if( $ok and $exportfile ) +{ + $ok = $aclEdit->exportACL( $exportfile, $exporttemplate ) ? $ok:0; +} + +if( $ok and $clearconf ) +{ + $ok = $aclEdit->clearConfig() ? $ok:0; +} + +if( @delgroups ) +{ + $ok = $aclEdit->deleteGroups( @delgroups ) ? $ok:0; +} + +if( @addgroups ) +{ + $ok = $aclEdit->addGroups( @addgroups ) ? $ok:0; +} + +if( @addgroups or @modgroups ) +{ + my $groups = [ @addgroups, @modgroups ]; + if( @permitprivs ) + { + $ok = setupPrivileges( $aclEdit, \@permitprivs, + $groups, \@forobjects, 1 ) ? $ok:0; + } + if( @denyprivs ) + { + $ok = setupPrivileges( $aclEdit, \@denyprivs, + $groups, \@forobjects, 0 ) ? $ok:0; + } +} + + +my $attrValues = {}; +my $uid; + +if( $commonname ) +{ + $attrValues->{'cn'} = $commonname; +} + +if( $adduser ) +{ + $uid = $adduser; + $ok = $aclEdit->addUser( $uid, $attrValues ) ? $ok:0; +} +elsif( $addhost ) +{ + $uid = $addhost; + $uid =~ s/\W/_/g; + $ok = $aclEdit->addUser( $uid, $attrValues ) ? $ok:0; +} + +elsif( $moduser ) +{ + $uid = $moduser; + if( scalar( keys %{$attrValues} ) ) + { + $ok = $aclEdit->setUserAttributes( $uid, $attrValues ) ? $ok:0; + } +} +elsif( $deluser ) +{ + $ok = $aclEdit->deleteUser( $deluser ) ? $ok:0; +} + +if( $uid ) +{ + if( $password ) + { + $ok = $aclEdit->setPassword( $uid, $password ) ? $ok:0; + } + elsif( $host_password ) + { + $ok = $aclEdit->setPassword( $uid, + $uid . '//' . $host_password ) ? $ok:0; + } +} + +if( $uid and scalar( @addtogroups ) ) +{ + $ok = $aclEdit->addUserToGroups( $uid, @addtogroups ) ? $ok:0; +} + +if( $uid and scalar( @delfromgroups ) ) +{ + $ok = $aclEdit->delUserFromGroups( $uid, @delfromgroups ) ? $ok:0; +} + +if( $ok and $importfile ) +{ + $ok = $aclEdit->importACL( $importfile ) ? $ok:0; +} + +if( $listall ) +{ + @showusers = $aclEdit->listUsers(); + @showgroups = $aclEdit->listGroups(); +} + +my %showGroupsHash; + +if( @showgroups ) +{ + foreach my $group ( @showgroups ) + { + if( $aclEdit->groupExists( $group ) ) + { + $showGroupsHash{$group} = 1; + } + else + { + Error('No such group: ' . $group); $ok = 0; + } + } +} + +if( @showusers ) +{ + foreach my $uid ( sort @showusers ) + { + if( $aclEdit->userExists( $uid ) ) + { + printf("User: %s (%s)\n", + $uid, $aclEdit->userAttribute( $uid, 'cn' ) ); + foreach my $group ( sort $aclEdit->memberOf( $uid ) ) + { + printf("Member of: %s\n", $group); + $showGroupsHash{$group} = 1; + } + + if( $verbose or $debug ) + { + printf("Modified: %s\n", + $aclEdit->userAttribute( $uid, 'modified' ) ); + } + printf ("\n"); + } + else + { + Error('No such user: ' . $uid); $ok = 0; + } + } +} + +if( %showGroupsHash ) +{ + foreach my $group ( sort keys %showGroupsHash ) + { + printf("Group: %s\n", $group); + + my $privs = $aclEdit->listPrivileges( $group ); + foreach my $object ( sort keys %{$privs} ) + { + foreach my $priv ( sort keys %{$privs->{$object}} ) + { + printf("Has privilege \"%s\" for %s \"%s\"\n", $priv, + $knownPrivileges{$priv}, $object); + } + } + + foreach my $uid ( sort @{$aclEdit->listGroupMembers( $group )} ) + { + printf("Member: %s\n", $uid); + } + + if( $verbose or $debug ) + { + printf("Modified: %s\n", + $aclEdit->groupAttribute( $group, 'modified' ) ); + } + + printf ("\n"); + } +} + +if( not $ok ) +{ + Warn('acledit exited with errors'); +} +exit( $ok ? 0:1 ); + +sub setupPrivileges +{ + my $aclEdtit = shift; + my $privs = shift; + my $groups = shift; + my $objects = shift; + my $permit = shift; + + my $ok = 1; + foreach my $priv ( @{$privs} ) + { + if( defined( $knownPrivileges{$priv} ) ) + { + if( $knownPrivileges{$priv} eq 'tree' ) + { + foreach my $obj ( @{$objects} ) + { + if( $obj eq '*' or + Torrus::SiteConfig::treeExists( $obj ) or $force ) + { + foreach my $group ( @{$groups} ) + { + if( $permit ) + { + $ok = $aclEdit-> + setPrivilege( $group, $obj, + $priv ) ? $ok:0; + } + else + { + $ok = $aclEdit-> + clearPrivilege( $group, $obj, + $priv ) ? $ok:0; + } + } + } + else + { + Error('No such tree: ' . $obj); $ok = 0; + } + } + } + elsif( $knownPrivileges{$priv} eq 'global' ) + { + foreach my $obj ( @{$objects} ) + { + if( $obj ne '*' ) + { + Error("Privilege GlobalSearch should be for '*'"); + $ok = 0; + } + } + + if( $ok ) + { + foreach my $group ( @{$groups} ) + { + if( $permit ) + { + $ok = $aclEdit-> + setPrivilege( $group, '*', $priv ) ? $ok:0; + } + else + { + $ok = $aclEdit-> + clearPrivilege( $group, '*', $priv ) ? $ok:0; + } + } + } + } + } + else + { + Error('Unknown privilege name: ' . $priv); $ok = 0; + } + } + return $ok; +} + + + + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/action_notify.in b/torrus/bin/action_notify.in new file mode 100644 index 000000000..a01b5486a --- /dev/null +++ b/torrus/bin/action_notify.in @@ -0,0 +1,96 @@ +#!@PERL@ +# Copyright (C) 2006 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: action_notify.in,v 1.1 2010-12-27 00:04:01 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +# We need this for $Torrus::Global::templateDirs +BEGIN { require '@torrus_config_pl@'; } + +use strict; +use Date::Format; + +use Torrus::Log; + +require '@notify_siteconfig_pl@'; + +if( not $ENV{'TORRUS_TREE'} ) +{ + print STDERR ("Torrus environment variables missing. This program ", + "must be run from Torrus Monitor\n"); + exit 1; +} + +our $now = time(); +our $nowHour = time2str('%H', $now); +our $nowWeekday = time2str('%w', $now); + +my $severity = $ENV{'TORRUS_SEVERITY'}; +my $ok = 1; + +foreach my $policy ( keys %Torrus::Notify::policies ) +{ + if( &{$Torrus::Notify::policies{$policy}{'match'}} ) + { + Debug('Notification policy matched: ' . $policy); + + my @targets = (); + my $levels = $Torrus::Notify::policies{$policy}{'severity'}; + + foreach my $level ( sort {$a <=>$b} keys %{$levels} ) + { + if( $severity >= $level ) + { + push( @targets, @{$levels->{$level}} ); + } + } + + if( isDebug() ) + { + Debug('Selected notification targets: ' . join(' ', @targets)); + } + + foreach my $target ( @targets ) + { + my($protocol, $arg) = split(':', $target); + if( defined( $Torrus::Notify::programs{$protocol} ) ) + { + $ENV{'ARG1'} = $arg; + my $status = system( $Torrus::Notify::programs{$protocol} ); + delete $ENV{'ARG1'}; + + if( $status != 0 ) + { + Error('The command "' . + $Torrus::Notify::programs{$protocol} . + '" returned error code ' . $status); + $ok = 0; + } + } + } + } +} + +exit( $ok ? 0:1 ); + + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/action_printemail.in b/torrus/bin/action_printemail.in new file mode 100644 index 000000000..416147b85 --- /dev/null +++ b/torrus/bin/action_printemail.in @@ -0,0 +1,83 @@ +#!@PERL@ +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: action_printemail.in,v 1.1 2010-12-27 00:04:03 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +# We need this for $Torrus::Global::templateDirs +BEGIN { require '@torrus_config_pl@'; } + +use strict; +use Template; +use Getopt::Long; + +require '@email_siteconfig_pl@'; + +if( not $ENV{'TORRUS_TREE'} ) +{ + print STDERR ("Torrus environment variables missing. This program ", + "must be run from Torrus Monitor\n"); + exit 1; +} + + +my $ok = GetOptions( 'url=s' => \$Torrus::Email::url, + 'template=s' => \$Torrus::Email::template ); + +if( not $ok ) +{ + print STDERR ("Error parsing options\n"); + exit 1; +} + +my $tt = new Template(INCLUDE_PATH => $Torrus::Global::templateDirs); + +my $vars = +{ + 'tree' => $ENV{'TORRUS_TREE'}, + 'token' => $ENV{'TORRUS_TOKEN'}, + 'path' => $ENV{'TORRUS_NODEPATH'}, + 'nickname' => $ENV{'TORRUS_NICKNAME'}, + 'url' => $Torrus::Email::url . '/' . + $ENV{'TORRUS_TREE'} . '?token='.$ENV{'TORRUS_TOKEN'}, + 'ncomment' => $ENV{'TORRUS_NCOMMENT'}, + 'npcomment' => $ENV{'TORRUS_NPCOMMENT'}, + 'event' => $ENV{'TORRUS_EVENT'}, + 'monitor' => $ENV{'TORRUS_MONITOR'}, + 'mcomment' => $ENV{'TORRUS_MCOMMENT'}, + 'severity' => $ENV{'TORRUS_SEVERITY'}, + 'timestamp' => scalar(localtime($ENV{'TORRUS_TSTAMP'})), + 'value' => $ENV{'TORRUS_VALUE'}, + 'dispvalue' => $ENV{'TORRUS_DISPLAY_VALUE'}, + 'env' => sub { return $ENV{$_[0]} } +}; + +my $result = $tt->process($Torrus::Email::template, $vars); + +if( not $result ) +{ + print STDERR "Error while processing template: ".$tt->error()."\n"; +} + +exit( $result ? 0:1 ); + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/action_snmptrap.in b/torrus/bin/action_snmptrap.in new file mode 100644 index 000000000..c2e9c20bb --- /dev/null +++ b/torrus/bin/action_snmptrap.in @@ -0,0 +1,183 @@ +#!@PERL@ +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: action_snmptrap.in,v 1.1 2010-12-27 00:04:01 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +# SNMP v2c trap +# See Torrus-MIB.txt for reference + +use strict; +use Net::SNMP qw(:ALL); +use Getopt::Long; + +require '@snmptrap_siteconfig_pl@'; + +if( not $ENV{'TORRUS_TOKEN'} ) +{ + print STDERR ("Torrus environment variables missing. This program ", + "must be run from Torrus Monitor\n"); + exit 1; +} + +my @hosts; +my $severity; + +my $ok = GetOptions( 'host=s' => \@hosts, + 'community=s' => \$Torrus::Snmptrap::community, + 'port=i' => \$Torrus::Snmptrap::port, + 'severity=i' => \$severity ); + +if( not $ok ) +{ + print STDERR ("Error parsing options\n"); + exit 1; +} + +if( scalar(@hosts) > 0 ) +{ + @Torrus::Snmptrap::hosts = @hosts; +} + +my $oid_prefix = '.1.3.6.1.4.1.14697.1.1.1'; + +my %event_type = ( 'set' => 1, + 'repeat' => 2, + 'clear' => 3, + 'forget' => 4 + ); + +my @varbindlist = ( $oid_prefix . '.1', + INTEGER32, 1, + + $oid_prefix . '.2', + OCTET_STRING, $ENV{'TORRUS_TOKEN'}, + + $oid_prefix . '.3', + OCTET_STRING, $ENV{'TORRUS_MONITOR'}, + + $oid_prefix . '.4', + INTEGER, $event_type{$ENV{'TORRUS_EVENT'}}, + + $oid_prefix . '.5', + OCTET_STRING, $ENV{'TORRUS_NODEPATH'}, + + $oid_prefix . '.6', + OCTET_STRING, snmp_dateandtime( $ENV{'TORRUS_TSTAMP'} ), + + $oid_prefix . '.7', + OCTET_STRING, $ENV{'TORRUS_TREE'}, + + $oid_prefix . '.9', + OCTET_STRING, $ENV{'TORRUS_MCOMMENT'} + ); + +if( defined( $severity ) ) +{ + push( @varbindlist, + $oid_prefix . '.8', + INTEGER32, $severity ); +} + + +foreach my $host ( @Torrus::Snmptrap::hosts ) +{ + my( $session, $error ) = + Net::SNMP->session( -hostname => $host, + -community => $Torrus::Snmptrap::community, + -port => $Torrus::Snmptrap::port, + -version => 2 + ); + + if( not defined($session) ) + { + printf STDERR ("Error opening SNMP trap session: %s.\n", $error); + exit 1; + } + + + my $result = + $session->snmpv2_trap( -varbindlist => \@varbindlist ); + + if( not $result ) + { + printf STDERR ("Error sending SNMP trap: %s.\n", $session->error()); + } + + $session->close(); +} + +# Converts UNIX time to DateAndTime from SNMPv2-TC +# Currently timezone is not handled. + +# DateAndTime ::= TEXTUAL-CONVENTION +# DISPLAY-HINT "2d-1d-1d,1d:1d:1d.1d,1a1d:1d" +# STATUS current +# DESCRIPTION +# "A date-time specification. +# +# field octets contents range +# ----- ------ -------- ----- +# 1 1-2 year* 0..65536 +# 2 3 month 1..12 +# 3 4 day 1..31 +# 4 5 hour 0..23 +# 5 6 minutes 0..59 +# 6 7 seconds 0..60 +# (use 60 for leap-second) +# 7 8 deci-seconds 0..9 +# 8 9 direction from UTC '+' / '-' +# 9 10 hours from UTC* 0..13 +# 10 11 minutes from UTC 0..59 +# +# * Notes: +# - the value of year is in network-byte order +# - daylight saving time in New Zealand is +13 +# +# For example, Tuesday May 26, 1992 at 1:30:15 PM EDT would be +# displayed as: +# +# 1992-5-26,13:30:15.0,-4:0 +# +# Note that if only local time is known, then timezone +# information (fields 8-10) is not present." +# SYNTAX OCTET STRING (SIZE (8 | 11)) + +sub snmp_dateandtime +{ + my $thetime = shift; + + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = + localtime( $thetime ); + + my $result = pack('nC6', + $year + 1900, + $mon + 1, + $mday, + $hour, + $min, + $sec, + 0); + return $result; +} + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/action_snmpv1trap.in b/torrus/bin/action_snmpv1trap.in new file mode 100644 index 000000000..02ec14a31 --- /dev/null +++ b/torrus/bin/action_snmpv1trap.in @@ -0,0 +1,134 @@ +#!@PERL@ +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: action_snmpv1trap.in,v 1.1 2010-12-27 00:04:02 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +# Obsoleted and not used SNMP v1 trap script. +# Version 2c is preferred one. + + +use strict; +use Net::SNMP qw(:ALL); +use Getopt::Long; + +require '@snmptrap_siteconfig_pl@'; + +# SNMP Enterprise. Needed for SNMP v1 trap. +# See http://www.iana.org/assignments/enterprise-numbers for reference +$Torrus::Snmptrap::enterprise = '1.3.6.1.4.1.14697.1.1.1'; + + +if( not $ENV{'TORRUS_TOKEN'} ) +{ + print STDERR ("Torrus environment variables missing. This program ", + "must be run from Torrus Monitor\n"); + exit 1; +} + +my @hosts; +my $severity; + +my $ok = GetOptions( 'host=s' => \@hosts, + 'community=s' => \$Torrus::Snmptrap::community, + 'port=i' => \$Torrus::Snmptrap::port, + 'enterprise' => \$Torrus::Snmptrap::enterprise, + 'severity=i' => \$severity ); + +if( not $ok ) +{ + print STDERR ("Error parsing options\n"); + exit 1; +} + +if( scalar(@hosts) > 0 ) +{ + @Torrus::Snmptrap::hosts = @hosts; +} + +my %specifictrap = ( 'set' => 1, + 'repeat' => 2, + 'clear' => 3, + 'forget' => 4 + ); + +my @varbindlist = ( $Torrus::Snmptrap::enterprise . '.2', + OCTET_STRING, $ENV{'TORRUS_TOKEN'}, + + $Torrus::Snmptrap::enterprise . '.5', + OCTET_STRING, $ENV{'TORRUS_NODEPATH'}, + + $Torrus::Snmptrap::enterprise . '.3', + OCTET_STRING, $ENV{'TORRUS_MONITOR'}, + + $Torrus::Snmptrap::enterprise . '.4', + OCTET_STRING, $ENV{'TORRUS_EVENT'}, + + $Torrus::Snmptrap::enterprise . '.6', + OCTET_STRING, scalar(localtime($ENV{'TORRUS_TSTAMP'})), + + $Torrus::Snmptrap::enterprise . '.7', + OCTET_STRING, $ENV{'TORRUS_TREE'}, + + $Torrus::Snmptrap::enterprise . '.9', + OCTET_STRING, $ENV{'TORRUS_MCOMMENT'} + ); + +if( defined( $severity ) ) +{ + push( @varbindlist, + $Torrus::Snmptrap::enterprise . '.8', + INTEGER32, $severity ); +} + +foreach my $host ( @Torrus::Snmptrap::hosts ) +{ + my( $session, $error ) = + Net::SNMP->session( -hostname => $host, + -community => $Torrus::Snmptrap::community, + -port => $Torrus::Snmptrap::port + ); + + if( not defined($session) ) + { + printf STDERR ("Error opening SNMP trap session: %s.\n", $error); + exit 1; + } + + + my $result = + $session->trap( -enterprise => $Torrus::Snmptrap::enterprise, + -generictrap => ENTERPRISE_SPECIFIC, + -specifictrap => $specifictrap{$ENV{'TORRUS_EVENT'}}, + -timestamp => $ENV{'TORRUS_UPTIME'} * 100, + -varbindlist => \@varbindlist + ); + + if( not $result ) + { + printf STDERR ("Error sending SNMP trap: %s.\n", $session->error()); + } + + $session->close(); +} + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/bdbinfo.in b/torrus/bin/bdbinfo.in new file mode 100644 index 000000000..c5628acbf --- /dev/null +++ b/torrus/bin/bdbinfo.in @@ -0,0 +1,38 @@ +#!@PERL@ -w +# Copyright (C) 2002-2008 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: bdbinfo.in,v 1.1 2010-12-27 00:04:03 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +BEGIN { require '@torrus_config_pl@'; } + +use strict; +use BerkeleyDB; + + +printf("MAJOR: %d\n", DB_VERSION_MAJOR); +printf("MINOR: %d\n", DB_VERSION_MINOR); +printf("PATCH: %d\n", DB_VERSION_PATCH); +printf("STRING: %s\n", DB_VERSION_STRING); + + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/buildsearchdb.in b/torrus/bin/buildsearchdb.in new file mode 100644 index 000000000..19c1ea8ff --- /dev/null +++ b/torrus/bin/buildsearchdb.in @@ -0,0 +1,200 @@ +#!@PERL@ -w +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: buildsearchdb.in,v 1.1 2010-12-27 00:04:01 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +BEGIN { require '@torrus_config_pl@'; } + +use strict; +use Getopt::Long; + +use Torrus::ConfigTree; +use Torrus::Search; +use Torrus::SiteConfig; +use Torrus::Log; + +exit(1) if not Torrus::SiteConfig::verify(); + +my @trees; +my $build_global; +my $all_trees; + +my $verbose; +my $help_needed; + +my $ok = GetOptions ('tree=s' => \@trees, + 'all' => \$all_trees, + 'global' => \$build_global, + 'verbose' => \$verbose, + 'help' => \$help_needed); + +if( not $ok or not (scalar(@trees) or $all_trees or $build_global) or + $help_needed or scalar(@ARGV) > 0 ) +{ + print STDERR "Usage: $0 --tree=NAME [options...]\n", + "Options:\n", + " --tree=NAME rebuild search DB for a tree\n", + " --all rebuild search DB for all trees\n", + " --global rebuild global search DB\n", + " --verbose print extra information\n", + " --help this help message\n"; + exit 1; +} + +if( $build_global ) +{ + $all_trees = 1; +} + +if( $all_trees ) +{ + @trees = Torrus::SiteConfig::listTreeNames(); +} + +if( $verbose ) +{ + Torrus::Log::setLevel('verbose'); +} + +&Torrus::DB::setSafeSignalHandlers(); + +Verbose(sprintf('Torrus version %s', '@VERSION@')); + +my $search = new Torrus::Search( -WriteAccess => 1 ); + +if( $build_global ) +{ + $search->openGlobal(); +} + +foreach my $tree ( @trees ) +{ + if( not Torrus::SiteConfig::treeExists( $tree ) ) + { + Error("Tree named \"" . $tree . "\" does not exist"); + exit(1); + } + + &Torrus::DB::checkInterrupted(); + + my $config_tree = new Torrus::ConfigTree( -TreeName => $tree ); + if( not defined($config_tree) ) + { + print("Configuration is not ready\n"); + exit(1); + } + + Verbose("Processing the tree: $tree"); + + $search->openTree( $tree ); + + walkSubtree( $config_tree, $search, $config_tree->token('/') ); + + $search->closeTree( $tree ); + $config_tree = undef; +} + +exit(0); + + +sub walkSubtree +{ + my $config_tree = shift; + my $search = shift; + my $ptoken = shift; + + my $tree = $config_tree->treeName(); + + foreach my $token ( $config_tree->getChildren( $ptoken ) ) + { + &Torrus::DB::checkInterrupted(); + + if( $config_tree->isSubtree( $token ) ) + { + walkSubtree( $config_tree, $search, $token ); + } + + my $isSearchable = + $config_tree->getNodeParam( $token, 'searchable', 1 ); + if( defined( $isSearchable ) and $isSearchable eq 'yes' ) + { + my $path = $config_tree->path( $token ); + + my $nodeName = $config_tree->nodeName( $path ); + splitAndStore( $tree, $nodeName, $path ); + + my $params = $config_tree->getParams( $token, 1 ); + while( my( $param, $value ) = each %{$params} ) + { + if( $config_tree->getParamProperty( $param, 'search' ) ) + { + splitAndStore( $tree, $value, $path, $param ); + } + } + } + } +} + + +sub splitAndStore +{ + my $tree = shift; + my $value = shift; + my $path = shift; + my $param = shift; + + if( length( $value ) > 0 ) + { + # split the value into words + my @words = split( /\W+/ms, $value ); + if( scalar( @words ) > 0 ) + { + foreach my $word ( @words ) + { + if( length( $word ) > 1 ) + { + $search->storeKeyword( $tree, $word, $path, $param ); + + # Split the word by underscores and minus + my @subwords = split( /_+/, $word ); + if( scalar( @subwords ) > 1 ) + { + foreach my $subword ( @subwords ) + { + if( length( $subword ) > 1 ) + { + $search->storeKeyword( $tree, + $subword, + $path, + $param ); + } + } + } + } + } + } + } +} + + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/cleanup.in b/torrus/bin/cleanup.in new file mode 100644 index 000000000..bc4f69fba --- /dev/null +++ b/torrus/bin/cleanup.in @@ -0,0 +1,32 @@ +#!@SHELL@ +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: cleanup.in,v 1.1 2010-12-27 00:04:03 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> +# + +# How soon the sessions expire +EXPIRE=60 + +@FIND@ @sesstordir@ -type f -mtime +$EXPIRE -exec @RM@ '{}' ';' +@FIND@ @seslockdir@ -type f -mtime +$EXPIRE -exec @RM@ '{}' ';' + +# Local Variables: +# mode: shell-script +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/clearcache.in b/torrus/bin/clearcache.in new file mode 100644 index 000000000..a3c0365d9 --- /dev/null +++ b/torrus/bin/clearcache.in @@ -0,0 +1,40 @@ +#!@PERL@ +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: clearcache.in,v 1.1 2010-12-27 00:04:01 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +BEGIN { require '@torrus_config_pl@'; } + +use Torrus::Log; + +use Torrus::Renderer; + +&Torrus::DB::setSafeSignalHandlers(); + +my $renderer = new Torrus::Renderer; +$renderer->clearcache(); +undef $renderer; + +Info('Renderer cache cleared'); +exit 0; + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/collector.in b/torrus/bin/collector.in new file mode 100644 index 000000000..e682fadc8 --- /dev/null +++ b/torrus/bin/collector.in @@ -0,0 +1,205 @@ +#!@PERL@ +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: collector.in,v 1.1 2010-12-27 00:04:03 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +BEGIN { require '@torrus_config_pl@'; } + +use strict; +use Proc::Daemon; +use Getopt::Long; + +use Torrus::Log; +use Torrus::ConfigTree; +use Torrus::Collector; +use Torrus::SiteConfig; + +$| = 1; + +exit(1) if not Torrus::SiteConfig::verify(); + +my $tree; +my $instance; +my $nodaemon; +my $runonce; +my $runalways; +my $debug; +my $verbose; +my $help_needed; + +# Derive the process name from the command line +my $process_name = $0; +$process_name =~ s/^.*\/([^\/]+)$/$1/; +$process_name .= ' ' . join(' ', @ARGV); + +my $ok = GetOptions ('tree=s' => \$tree, + 'instance=i' => \$instance, + 'nodaemon' => \$nodaemon, + 'runonce' => \$runonce, + 'runalways' => \$runalways, + 'debug' => \$debug, + 'verbose' => \$verbose, + 'help' => \$help_needed); + +if( not $ok or not $tree or $help_needed or scalar(@ARGV) > 0 ) +{ + print STDERR "Usage: $0 --tree=NAME [options...]\n", + "Options:\n", + " --tree=NAME tree name\n", + " --instance=N instance number for multiple collectors per tree\n", + " --nodaemon do not fork daemon and log to STDERR\n", + " --runonce run one time and exit. Implies --nodaemon\n", + " --runalways continue running if no collectors defined\n", + " --debug set the log level to debug\n", + " --verbose set the log level to info\n", + " --help this help message\n"; + exit 1; +} + +if( not Torrus::SiteConfig::mayRunCollector( $tree ) ) +{ + Error('Tree ' . $tree . ' is not configured to run collector'); + exit 1; +} + +my $nInstances = Torrus::SiteConfig::collectorInstances( $tree ); + +if( $nInstances > 1 and not defined( $instance ) ) +{ + Error('--instance option is missing'); + exit 1; +} + +if( not defined( $instance ) ) +{ + $instance = 0; +} + +if( $instance >= $nInstances ) +{ + Error('Invalid instance number. Allowed from 0 to ' . ($nInstances-1)); + exit 1; +} + +if( $debug ) +{ + Torrus::Log::setLevel('debug'); +} +elsif( $verbose ) +{ + Torrus::Log::setLevel('verbose'); +} + +my $logfile = + $Torrus::Global::logDir . '/collector.' . $tree . '_' . $instance . '.log'; +my $pidfile; + +my $rotateLogs = sub +{ + Info('Caught SIGHUP. Reopening log file'); + close( STDERR ); + open( STDERR, ">>$logfile" ); + $| = 1; +}; + +if( not $nodaemon and not $runonce ) +{ + my $pidfilename = + $Torrus::Global::pidDir . '/collector.' . + $tree . '_' . $instance . '.pid'; + + if( -r $pidfilename ) + { + Error("Another collector daemon is running, pid=", + `cat $pidfilename`); + exit 1; + } + + &Proc::Daemon::Init(); + umask 0017; # Proc::Daemon::Init sets the mask to all-writable + + $SIG{'HUP'} = $rotateLogs; + + # At this point, we cannot tell anyone if "open" fails + open(STDERR, ">>$logfile"); + + $pidfile = $pidfilename; + + if( open( PID, ">$pidfile" ) ) + { + printf PID ( "%d", $$ ); + close PID; + } + else + { + Error("Cannot open $pidfile for writing: $!"); + } +} + + +Torrus::Collector::initThreads(); + +&Torrus::DB::setSafeSignalHandlers(); + + +Info(sprintf("Torrus version %s", '@VERSION@')); +Info(sprintf("%s started for tree %s, instance #%d", $0, $tree, $instance)); +Debug(sprintf("Process ID %d", $$)); + +my %options = + ( + '-ProcessName' => $process_name, + '-Tree' => $tree, + '-Instance' => $instance + ); + +if( $runonce ) +{ + $options{'-RunOnce'} = 1; +} +if( $runalways ) +{ + $options{'-RunAlways'} = 1; +} + + +my $scheduler = new Torrus::CollectorScheduler( %options ); +$scheduler->run(); + +if( not $options{'-RunOnce'} ) +{ + Error("Collector process exited: nothing to collect"); + unlink $pidfile; +} + +exit; + + +END +{ + if( defined($pidfile) and -r $pidfile ) + { + unlink $pidfile; + } +} + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/compilexml.in b/torrus/bin/compilexml.in new file mode 100644 index 000000000..56bbada0a --- /dev/null +++ b/torrus/bin/compilexml.in @@ -0,0 +1,207 @@ +#!@PERL@ -w +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: compilexml.in,v 1.1 2010-12-27 00:04:00 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +BEGIN { require '@torrus_config_pl@'; } + +use Getopt::Long; +use strict; + +use Torrus::ConfigTree::XMLCompiler; +use Torrus::SiteConfig; +use Torrus::Log; + +exit(1) if not Torrus::SiteConfig::verify(); + +our @trees; +our $all_trees; +our $no_ds; +our $no_validation; +our $force; + +our $debug; +our $verbose; +our $help_needed; + +my $ok = GetOptions ('tree=s' => \@trees, + 'all' => \$all_trees, + 'nods' => \$no_ds, + 'noval' => \$no_validation, + 'force' => \$force, + 'debug' => \$debug, + 'verbose' => \$verbose, + 'help' => \$help_needed); + +if( not $ok or not (scalar(@trees) or $all_trees) or + $help_needed or scalar(@ARGV) > 0 ) +{ + print STDERR "Usage: $0 --tree=NAME [options...]\n", + "Options:\n", + " --tree=NAME tree name(s) to compile\n", + " --all compile all trees\n", + " --nods compile non-datasource configuration only\n", + " --noval disable parameter validation\n", + " --force force the compiler even if anoother " . + "compiler process is probably running\n", + " --debug set the log level to debug\n", + " --verbose set the log level to info\n", + " --help this help message\n"; + exit 1; +} + +if( $all_trees ) +{ + @trees = Torrus::SiteConfig::listTreeNames(); +} + +if( $debug ) +{ + Torrus::Log::setLevel('debug'); +} +elsif( $verbose ) +{ + Torrus::Log::setLevel('verbose'); +} + + +&Torrus::DB::setSafeSignalHandlers(); + +Verbose(sprintf('Torrus version %s', '@VERSION@')); + +our $global_ok = 1; + +foreach my $tree ( @trees ) +{ + if( not Torrus::SiteConfig::treeExists( $tree ) ) + { + Error("Tree named \"" . $tree . "\" does not exist"); + exit(1); + } + + &Torrus::DB::checkInterrupted(); + + Verbose("Compiling tree: $tree"); + + my $ok = 1; + my $compiler = + new Torrus::ConfigTree::XMLCompiler( -TreeName => $tree, + -NoDSRebuild => $no_ds, + -ForceWriter => $force ); + if( not defined( $compiler ) ) + { + Error('Cannot initialize compiler for tree ' . $tree . '. Exiting'); + Error('If you are sure there are no other compiler processes ' . + 'running, use the --force option'); + $global_ok = 0; + last; + } + + my @xmlFiles = @Torrus::Global::xmlAlwaysIncludeFirst; + push( @xmlFiles, Torrus::SiteConfig::listXmlFiles( $tree ) ); + push( @xmlFiles, @Torrus::Global::xmlAlwaysIncludeLast ); + + foreach my $xmlfile ( @xmlFiles ) + { + if( not $compiler->compile( $xmlfile ) ) + { + Error($xmlfile . ' compiled with errors'); $ok = 0; + } + } + + if( not $ok ) + { + Error("Errors found during XML compilation in the tree named \"" . + $tree . "\""); + $global_ok = 0; + last; + } + + Verbose('Data post-processing...'); + if( not $compiler->postProcess() ) + { + Error('Errors found during post-processing'); + $ok = 0; + } + + if( $no_validation ) + { + Verbose('Skipping data validation...'); + } + else + { + Verbose('Data validation...'); + if( not $compiler->validate() ) + { + Error('Errors found during validation process'); + $ok = 0; + } + } + + &Torrus::DB::checkInterrupted(); + + # Preserve the dynamic tokenset members + if( not $compiler->{'first_time_created'} ) + { + my $oldConfig = new Torrus::ConfigTree( -TreeName => $tree ); + if( defined( $oldConfig ) ) + { + foreach my $ts ( $oldConfig->getTsets() ) + { + if( $compiler->tsetExists( $ts ) ) + { + foreach my $member ( $oldConfig->tsetMembers( $ts ) ) + { + my $origin = $oldConfig->tsetMembers( $ts, $member ); + if( defined( $origin ) and $origin ne 'static' ) + { + my $path = $oldConfig->path($member); + if( $compiler->nodeExists( $path ) ) + { + my $token = $compiler->token( $path ); + $compiler->tsetAddMember + ( $ts, $token, $origin ); + Verbose('Preserved dynamic tokenset member: ' . + $path . ' in ' . $ts); + } + } + } + } + } + } + + undef $oldConfig; + } + + &Torrus::DB::checkInterrupted(); + + $compiler->finalize( $ok ); + undef $compiler; + &Torrus::DB::cleanupEnvironment(); + + $global_ok = $ok ? $global_ok:0; +} + +exit($global_ok ? 0:1); + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/configinfo.in b/torrus/bin/configinfo.in new file mode 100644 index 000000000..1b985f88c --- /dev/null +++ b/torrus/bin/configinfo.in @@ -0,0 +1,166 @@ +#!@PERL@ -w +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: configinfo.in,v 1.1 2010-12-27 00:04:03 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +BEGIN { require '@torrus_config_pl@'; } + +use strict; +use BerkeleyDB; + +use Torrus::ConfigTree; +use Torrus::TimeStamp; +use Torrus::SiteConfig; +use Torrus::Log; + +exit(1) if not Torrus::SiteConfig::verify(); + +&Torrus::DB::setSafeSignalHandlers(); + +Torrus::TimeStamp::init(); + +my @tree_names = Torrus::SiteConfig::listTreeNames(); + + +printf("Torrus version %s\n", '@VERSION@'); +printf("%s\n", DB_VERSION_STRING); +printf("BerkeleyDB.pm version %s\n", $BerkeleyDB::VERSION); +printf("\n"); + +printf("Datasource trees: %d\n", scalar( @tree_names ) ); +printf("Tree names: %s\n", join(', ', @tree_names) ); +printf("\n"); + +foreach my $tree ( @tree_names ) +{ + &Torrus::DB::checkInterrupted(); + + printf("Tree: %s\n", $tree ); + + my $config_tree = new Torrus::ConfigTree( -TreeName => $tree ); + if( not defined($config_tree) ) + { + print("Configuration is not ready\n"); + } + else + { + my $stats = {}; + foreach my $name ( 'leaves', 'collectorLeaves', 'monitorLeaves', + 'holtwintersLeaves', 'subtrees', + 'maxSubtreePath', 'maxSubtreeSize', 'views', + 'monitors', 'actions', 'compiled' ) + { + $stats->{$name} = 0; + } + + collectStats( $config_tree, $stats ); + collectOtherStats( $config_tree, $stats ); + + printf("Leaves: %d\n", $stats->{'leaves'} ); + printf("Collector leaves: %d\n", $stats->{'collectorLeaves'} ); + printf("Monitor leaves: %d\n", $stats->{'monitorLeaves'} ); + printf("Holt-Winters leaves: %d\n", $stats->{'holtwintersLeaves'} ); + printf("Subtrees: %d\n", $stats->{'subtrees'} ); + printf("Largest subtree: %s\n", $stats->{'maxSubtreePath'} ); + printf("Largest subtree size: %d\n", $stats->{'maxSubtreeSize'} ); + printf("Views: %d\n", $stats->{'views'} ); + printf("Monitors: %d\n", $stats->{'monitors'} ); + printf("Actions: %d\n", $stats->{'actions'} ); + printf("Last compiled: %s\n", + scalar(localtime($stats->{'compiled'}))); + printf("\n"); + } +} + + +sub collectStats +{ + my $config_tree = shift; + my $stats = shift; + my $token = shift; + + &Torrus::DB::checkInterrupted(); + + if( not defined( $token ) ) + { + $token = $config_tree->token('/'); + } + + my @children = $config_tree->getChildren( $token ); + + my $nChildren = scalar( @children ); + if( not defined( $stats->{'maxSubtreeSize'} ) or + $stats->{'maxSubtreeSize'} < $nChildren ) + { + $stats->{'maxSubtreeSize'} = $nChildren; + $stats->{'maxSubtreePath'} = $config_tree->path( $token ); + } + + foreach my $ctoken ( @children ) + { + if( $config_tree->isSubtree( $ctoken ) ) + { + $stats->{'subtrees'}++; + collectStats( $config_tree, $stats, $ctoken ); + } + elsif( $config_tree->isLeaf( $ctoken ) ) + { + $stats->{'leaves'}++; + if( $config_tree->getNodeParam( $ctoken, 'ds-type' ) + eq 'collector' ) + { + $stats->{'collectorLeaves'}++; + } + if( defined( $config_tree->getNodeParam( $ctoken, 'monitor' ) ) ) + { + $stats->{'monitorLeaves'}++; + } + my $val = $config_tree->getNodeParam( $ctoken, 'rrd-hwpredict' ); + if( defined( $val ) and $val eq 'enabled' ) + { + $stats->{'holtwintersLeaves'}++; + } + } + } +} + + +sub collectOtherStats +{ + my $config_tree = shift; + my $stats = shift; + + my $n = scalar( $config_tree->getViewNames() ); + $stats->{'views'} = $n if defined( $n ); + + $n = scalar( $config_tree->getMonitorNames() ); + $stats->{'monitors'} = $n if defined( $n ); + + $n = scalar( $config_tree->getActionNames() ); + $stats->{'actions'} = $n if defined( $n ); + + $n = $config_tree->getTimestamp(); + $stats->{'compiled'} = $n if defined( $n ); +} + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/configsnapshot.in b/torrus/bin/configsnapshot.in new file mode 100644 index 000000000..dc79e5bdb --- /dev/null +++ b/torrus/bin/configsnapshot.in @@ -0,0 +1,332 @@ +#!@PERL@ +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: configsnapshot.in,v 1.1 2010-12-27 00:04:01 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +BEGIN { require '@torrus_config_pl@'; } + +use strict; +use Getopt::Long; + +use Torrus::Log; +use Torrus::ConfigTree; +use Torrus::SiteConfig; +use Torrus::ConfigBuilder; + +exit(1) if not Torrus::SiteConfig::verify(); + +my $tree; +my $help_needed; +my $verbose = 0; + +my $outfile = 'snapshot.xml'; + +my $filter_param; +my $filter_value; +my $filter_op = '='; + +my $creator = "Torrus version @VERSION@\n" . + "This file was generated by command:\n" . + $0 . " \\\n"; +foreach my $arg ( @ARGV ) +{ + if( $arg =~ /^--/ ) + { + $creator .= ' ' . $arg . ' '; + } + else + { + $creator .= "\'" . $arg . "\'\\\n"; + } +} +$creator .= "\nOn " . scalar(localtime(time)); + +my $ok = GetOptions('tree=s' => \$tree, + 'out=s' => \$outfile, + 'param=s' => \$filter_param, + 'value=s' => \$filter_value, + 'op=s' => \$filter_op, + 'verbose' => \$verbose, + 'help' => \$help_needed); + +if( not $ok or not $tree or $help_needed or + ( defined($filter_param) + defined($filter_value) == 1 ) or + ( $filter_op ne '=' and $filter_op ne 'eq' and $filter_op ne 're' ) or + scalar(@ARGV) > 0 ) +{ + print STDERR "Usage: $0 --tree=NAME [options...]\n", + "Options:\n", + " --tree=NAME tree name\n", + " --out=filename output file [".$outfile."]\n", + " --param=PARAM --value=VALUE \n", + " filter the output by leaves with specified value\n", + " --op=OP filter operation [=|eq|re], default: [=]\n", + " --verbose print extra information\n", + " --help this help message\n"; + exit 1; +} + +if( $verbose ) +{ + Torrus::Log::setLevel('verbose'); +} + +if( not Torrus::SiteConfig::treeExists( $tree ) ) +{ + Error('Tree ' . $tree . ' does not exist'); + exit 1; +} + +&Torrus::DB::setSafeSignalHandlers(); + +my $config_tree = new Torrus::ConfigTree( -TreeName => $tree, -Wait => 1 ); +if( not defined( $config_tree ) ) +{ + exit 1; +} + + +my $filter_match = sub {return $_[0] == $filter_value}; + +if(defined($filter_param)) +{ + if( $filter_op eq 'eq' ) + { + $filter_match = sub {return $_[0] eq $filter_value}; + } + elsif( $filter_op eq 're' ) + { + $filter_match = sub {return $_[0] =~ $filter_value}; + } +} + + + +my $cb = new Torrus::ConfigBuilder; + +$cb->addCreatorInfo( $creator ); + +# We don't collect views, since they are in defaults.xml which is always +# included + +collect_monitors( $config_tree, $cb ); +collect_tokensets( $config_tree, $cb ); +collect_definitions( $config_tree, $cb ); +collect_datasources( $config_tree, $cb ); + +my $ok = $cb->toFile( $outfile ); +if( $ok ) +{ + Verbose('Wrote ' . $outfile); +} +else +{ + Error('Cannot write ' . $outfile . ': ' . $!); +} + +exit($ok ? 0:1); + +sub collect_monitors +{ + my $config_tree = shift; + my $cb = shift; + + my $monitorsNode = $cb->startMonitors(); + + foreach my $action ( $config_tree->getActionNames() ) + { + &Torrus::DB::checkInterrupted(); + + my $params = $config_tree->getParams( $action ); + $cb->addMonitorAction( $monitorsNode, $action, $params ); + } + + foreach my $monitor ( $config_tree->getMonitorNames() ) + { + &Torrus::DB::checkInterrupted(); + + my $params = $config_tree->getParams( $monitor ); + $cb->addMonitor( $monitorsNode, $monitor, $params ); + } +} + +sub collect_tokensets +{ + my $config_tree = shift; + my $cb = shift; + + my $tsetsNode = $cb->startTokensets(); + + foreach my $tset ( $config_tree->getTsets() ) + { + &Torrus::DB::checkInterrupted(); + + my $params = $config_tree->getParams( $tset ); + my $name = $tset; + $name =~ s/^S//; + $cb->addTokenset( $tsetsNode, $name, $params ); + } +} + + +sub collect_definitions +{ + my $config_tree = shift; + my $cb = shift; + + my $definitionsNode = $cb->startDefinitions(); + + foreach my $defName ( sort $config_tree->getDefinitionNames() ) + { + &Torrus::DB::checkInterrupted(); + + my $value = $config_tree->getDefinition( $defName ); + $cb->addDefinition( $definitionsNode, $defName, $value ); + } + + my $propsNode = $cb->startParamProps(); + my $props = $config_tree->getParamProperties(); + + &Torrus::DB::checkInterrupted(); + + foreach my $prop ( sort keys %{$props} ) + { + foreach my $param ( sort keys %{$props->{$prop}} ) + { + $cb->addParamProp( $propsNode, $param, $prop, + $props->{$prop}{$param} ); + } + } +} + + +my %filterTokens; + + +sub collect_datasources +{ + my $config_tree = shift; + my $cb = shift; + + my $topNode = $cb->getTopSubtree(); + my $topToken = $config_tree->token('/'); + + my $params = prepare_params( $config_tree, $topToken ); + $cb->addParams( $topNode, $params ); + + if( defined($filter_param) ) + { + $filterTokens{$topToken} = apply_filter( $config_tree, $topToken ); + } + + collect_subtrees( $config_tree, $cb, $topToken, $topNode ); +} + + + +sub apply_filter +{ + my $config_tree = shift; + my $token = shift; + + $filterTokens{$token} = 0; + + foreach my $ctoken ( $config_tree->getChildren( $token ) ) + { + &Torrus::DB::checkInterrupted(); + + if( $config_tree->isSubtree( $ctoken ) ) + { + $filterTokens{$token} += apply_filter( $config_tree, $ctoken ); + } + elsif( $config_tree->isLeaf( $ctoken ) ) + { + my $val = $config_tree->getNodeParam( $ctoken, $filter_param ); + if( defined($val) and &{$filter_match}($val) ) + { + $filterTokens{$ctoken} = 1; + $filterTokens{$token}++; + } + } + } + + return $filterTokens{$token}; +} + + + +sub collect_subtrees +{ + my $config_tree = shift; + my $cb = shift; + my $token = shift; + my $parentNode = shift; + + foreach my $ctoken ( $config_tree->getChildren( $token ) ) + { + &Torrus::DB::checkInterrupted(); + + if( not defined($filter_param) or $filterTokens{$ctoken} ) + { + my $childName = + $config_tree->nodeName( $config_tree->path($ctoken) ); + my $params = prepare_params( $config_tree, $ctoken ); + + if( $config_tree->isSubtree( $ctoken ) ) + { + my $subtreeNode = + $cb->addSubtree( $parentNode, $childName, $params ); + collect_subtrees( $config_tree, $cb, $ctoken, $subtreeNode ); + } + elsif( $config_tree->isLeaf( $ctoken ) ) + { + $cb->addLeaf( $parentNode, $childName, $params ); + } + + foreach my $aliasToken ( $config_tree->getAliases( $ctoken ) ) + { + $cb->addAlias( $parentNode, + $config_tree->path( $aliasToken ) ); + } + } + } +} + + +sub prepare_params +{ + my $config_tree = shift; + my $token = shift; + + my $params = $config_tree->getParams( $token, 1 ); + + # Remove linebreaks + while( my( $param, $value ) = each %{$params} ) + { + $value =~ s/\s+/ /gm; + $params->{$param} = $value; + } + + return $params; +} + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/devdiscover.in b/torrus/bin/devdiscover.in new file mode 100644 index 000000000..f11372308 --- /dev/null +++ b/torrus/bin/devdiscover.in @@ -0,0 +1,619 @@ +#!@PERL@ +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: devdiscover.in,v 1.1 2010-12-27 00:04:02 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +# Collect the router information and create the XML file + +BEGIN { require '@devdiscover_config_pl@'; } + +use strict; +use Getopt::Long; +use XML::LibXML; + +use Torrus::Log; +use Torrus::DevDiscover; +use Torrus::ConfigBuilder; + +$| = 1; + +my @infiles; +my $makedirs; +my $limitre; +my $forcebundle; +my $fallback; +my $workerThreads = 0; + +# Hidden parameter for debugging +my $snmpdebug = 0; +my $debug = 0; +my $verbose = 0; + +my %formatsSupported = ( '1.0' => 1 ); + + +my $creator = "Torrus version @VERSION@\n" . + "This file was generated by command:\n" . + $0 . " \\\n"; +foreach my $arg ( @ARGV ) +{ + if( $arg =~ /^--/ ) + { + $creator .= ' ' . $arg . ' '; + } + else + { + $creator .= "\'" . $arg . "\'\\\n"; + } +} +$creator .= "\n On " . scalar(localtime(time)); + +my $ok = GetOptions( + 'in=s' => \@infiles, + 'mkdir' => \$makedirs, + 'limit=s' => \$limitre, + 'forcebundle' => \$forcebundle, + 'fallback=i' => \$fallback, + 'threads=i' => \$workerThreads, + 'snmpdebug' => \$snmpdebug, + 'verbose' => \$verbose, + 'debug' => \$debug + ); +if( $ok and scalar( @ARGV ) > 0 ) +{ + push( @infiles, @ARGV ); +} + +if( not $ok or scalar(@infiles) == 0 or + ($workerThreads > 1 and not $Torrus::Global::threadsEnabled ) ) +{ + print STDERR "Usage: $0 --in=filename.ddx options... [ddx files]\n", + "Options:\n", + " --in=filename.ddx discovery instructions XML file(s)\n", + " --mkdir create data-dir directories\n", + " --limit=regexp limit the discovery by output files\n", + " --forcebundle always write the bundle file\n", + " --fallback=integer maximum age of XML file to fall back to\n", + " --threads=integer number of parallel discovery threads\n", + " --verbose print extra information\n", + " --debug print debugging information\n", + " --snmpdebug print SNMP protocol details\n", + "\n"; + if( not $Torrus::Global::threadsEnabled ) + { + print STDERR "Multithreading is NOT SUPPORTED by current " . + "perl interpreter\n"; + } + + exit 1; +} + +if( $snmpdebug ) +{ + $Net::SNMP::Transport::UDP::DEBUG = 1; + $Net::SNMP::Message::DEBUG = 1; + $Net::SNMP::MessageProcessing::DEBUG = 1; + $Net::SNMP::Dispatcher::DEBUG = 1; +} + +if( $debug ) +{ + Torrus::Log::setLevel('debug'); +} +elsif( $verbose ) +{ + Torrus::Log::setLevel('verbose'); +} + +my $everythingsOk = 1; +my $perOutfileHostParams = {}; +my %outputBundles; + +foreach my $infile ( @infiles ) +{ + if( not -r $infile ) + { + my $altfile = $Torrus::Global::discoveryDir . $infile; + if( not -r $altfile ) + { + Error('Cannot find file ' . $infile . + ' neither in current directory nor in ' . + $Torrus::Global::discoveryDir); + exit 1; + } + else + { + $infile = $altfile; + } + } + + Verbose('Processing ' . $infile); + + my $parser = new XML::LibXML; + my $doc; + eval { $doc = $parser->parse_file( $infile ); }; + if( $@ ) + { + Error("Failed to parse $infile: $@"); + exit 1; + } + + my $root = $doc->documentElement(); + if( $root->nodeName() ne 'snmp-discovery' ) + { + Error('XML root element is not "snmp-discovery" in ' . $infile); + exit 1; + } + + my $format_version = + (($root->getElementsByTagName('file-info'))[0]-> + getElementsByTagName('format-version'))[0]->textContent(); + + $format_version =~ s/\s//g; + + if( not $format_version or not $formatsSupported{$format_version} ) + { + Error('Invalid format or format version not supported: ' . $infile); + exit 1; + } + + my $globalParams = parseParams( $root ); + + + # Parse the body of the XML + + foreach my $hostNode ( $root->getChildrenByTagName('host') ) + { + my $hostParams = parseParams( $hostNode, $globalParams ); + normalizeParams( $hostParams ); + + my $outfile = $hostParams->{'output-file'}; + if( not exists($perOutfileHostParams->{$outfile}) ) + { + $perOutfileHostParams->{$outfile} = []; + } + push( @{$perOutfileHostParams->{$outfile}}, $hostParams ); + + my $outBundles = $hostParams->{'output-bundle'}; + if( length( $outBundles ) > 0 ) + { + foreach my $bundleName ( split( /\s*,\s*/, $outBundles ) ) + { + $bundleName = absXmlFilename( $bundleName ); + $outputBundles{$bundleName}{ relXmlFilename($outfile) } = 1; + } + } + } +} + + +# Start discovery +my $jobQueue; +my $bundleDeletionQueue; +my $confBuildSemaphore; + +if( $workerThreads > 1 ) +{ + require threads; + require threads::shared; + require Thread::Queue; + require Thread::Semaphore; + + threads::shared::share( \$everythingsOk ); + + $jobQueue = new Thread::Queue; + $bundleDeletionQueue = new Thread::Queue; + $confBuildSemaphore = new Thread::Semaphore; + + # Enqueue the output filenames + foreach my $outfile ( sort keys %{$perOutfileHostParams} ) + { + if( not matchLimitRe( $outfile ) ) + { + next; + } + + $jobQueue->enqueue( $outfile ); + } + + # Start the worker threads + my @workers; + foreach my $i ( 1..$workerThreads ) + { + push( @workers, threads->create( \&discoveryThread ) ); + } + + # Wait for workers to finish the jobs + while( my $thr = shift( @workers ) ) + { + my $tid = $thr->tid(); + $thr->join(); + Debug('Cleaning up thread #' . $tid); + undef $thr; + } + + # Process the files to be excluded from bundles + + if( not $everythingsOk ) + { + my $outfile; + while( defined( $outfile = $bundleDeletionQueue->dequeue_nb() ) ) + { + removeFromBundle( $outfile ); + } + } +} +else +{ + # Single-thread operation + + foreach my $outfile ( sort keys %{$perOutfileHostParams} ) + { + if( not matchLimitRe( $outfile ) ) + { + next; + } + + if( not doDiscover( $outfile ) ) + { + removeFromBundle( $outfile ); + } + } +} + +# Discovery finished, do the bundles + +if( scalar( keys %outputBundles ) > 0 ) +{ + if( defined( $limitre ) ) + { + Warn('Cannot write bundles with --limit option specified. ' . + 'Bundle files remain unchanged'); + } + elsif( $everythingsOk ) + { + foreach my $bundleName ( sort keys %outputBundles ) + { + my $cb = new Torrus::ConfigBuilder; + + $cb->addCreatorInfo( $creator ); + + foreach my $bundleMember + ( sort keys %{$outputBundles{$bundleName}} ) + { + $cb->addFileInclusion( $bundleMember ); + } + + my $ok = $cb->toFile( $bundleName ); + if( $ok ) + { + Verbose('Wrote bundle to ' . $bundleName); + } + else + { + Error('Cannot write bundle to ' . $bundleName . ': ' . $!); + $everythingsOk = 0; + } + } + } + else + { + Error('Skipping bundles generation because of errors'); + } +} + + +exit($everythingsOk ? 0:1); + + +sub parseParams +{ + my $parentNode = shift; + my $paramhash = shift; + + # Clone the parameters hash + my $ret = {}; + if( $paramhash ) + { + while( my($key, $val) = each %{$paramhash} ) + { + $ret->{$key} = $val; + } + } + + foreach my $paramNode ( $parentNode->getChildrenByTagName('param') ) + { + my $param = $paramNode->getAttribute('name'); + my $value = $paramNode->getAttribute('value'); + + if( not $param ) + { + Error("Parameter without name"); + exit 1; + } + + if( not defined( $value ) ) + { + $value = $paramNode->textContent(); + } + + # Remove spaces in the head and tail. + $value =~ s/^\s+//; + $value =~ s/\s+$//; + + $ret->{$param} = $value; + } + return $ret; +} + + +sub normalizeParams +{ + my $params = shift; + + if( not defined( $params->{'output-file'} ) ) + { + Warn('output-file parameter is not defined. Using routers.xml'); + $params->{'output-file'} = 'routers.xml'; + } + else + { + $params->{'output-file'} = absXmlFilename( $params->{'output-file'} ); + } + + if( defined( $params->{'host-subtree'} ) ) + { + my $subtree = $params->{'host-subtree'}; + + if( $subtree !~ /^\/[0-9A-Za-z_\-\.\/]*$/ or + $subtree =~ /\.\./ ) + { + Error("Invalid format for subtree name: " . $subtree); + exit 1; + } + } + + if( defined( $params->{'snmp-community'} ) ) + { + # Remove any possible Unicode character treatment + $params->{'snmp-community'} = + pack( 'A*', $params->{'snmp-community'} ); + } +} + + +# Replaces $XMLCONFIG with the XML root directory +sub absXmlFilename +{ + my $filename = shift; + + my $subst = '$XMLCONFIG'; + my $offset = index( $filename, $subst ); + if( $offset >= 0 ) + { + my $len = length( $subst ); + substr( $filename, $offset, $len ) = $Torrus::Global::siteXmlDir; + } + else + { + if( $filename !~ /^\// ) + { + $filename = $Torrus::Global::siteXmlDir . '/' . $filename; + } + } + return $filename; +} + + +# Removes XML root directory from path +sub relXmlFilename +{ + my $filename = shift; + + my $subst = $Torrus::Global::siteXmlDir; + my $len = length( $subst ); + + if( $filename =~ /^\// ) + { + my $offset = index( $filename, $subst ); + if( $offset == 0 ) + { + $filename = substr( $filename, $len ); + # we don't know if xmldir has a trailing slash + $filename =~ s/^\///; + } + } + return $filename; +} + + +sub matchLimitRe +{ + my $filename = shift; + + if( defined( $limitre ) ) + { + $filename =~ s/^.*\///; + + if( $filename !~ $limitre ) + { + return 0; + } + } + + return 1; +} + + +# Pick up next available outfile until the job queue is empty + +sub discoveryThread +{ + Torrus::Log::setTID( threads->tid() ); + Debug('Started thread #' . threads->tid()); + my $outfile; + while( defined( $outfile = $jobQueue->dequeue_nb() )) + { + if( not doDiscover( $outfile ) ) + { + $bundleDeletionQueue->enqueue( $outfile ); + } + } + Debug('Finished thread #' . threads->tid()); +} + + + +sub doDiscover +{ + my $outfile = shift; + + Verbose('Preparing to write ' . $outfile); + + my $dd = new Torrus::DevDiscover; + my $ok = 1; + + foreach my $hostParams ( @{$perOutfileHostParams->{$outfile}} ) + { + $ok = $dd->discover( $hostParams ); + + if( not $ok ) + { + Error($outfile . ' was not written because of errors'); + $everythingsOk = 0; + last; + } + } + + if( $ok ) + { + # LibXML2 is not thread-safe, so we create the XML files + # one at a time + if( $workerThreads > 1 ) + { + $confBuildSemaphore->down(); + } + + my $cb = new Torrus::ConfigBuilder; + + $cb->addCreatorInfo( $creator ); + + $dd->buildConfig( $cb ); + $cb->addRequiredFiles(); + $cb->addStatistics(); + + $ok = $cb->toFile( $outfile ); + if( $ok ) + { + Verbose('Wrote ' . $outfile); + } + else + { + Error('Cannot write ' . $outfile . ': ' . $!); + $everythingsOk = 0; + } + + if( $workerThreads > 1 ) + { + $confBuildSemaphore->up(); + } + } + + if( $makedirs ) + { + if( $everythingsOk ) + { + # Not sure if these calls are reentrant + if( $workerThreads > 1 ) + { + $confBuildSemaphore->down(); + } + + my ($login,$pass,$uid,$gid) = getpwnam('@torrus_user@') + or die "Cannot get user details for @torrus_user@"; + + foreach my $dir ( $dd->listDataDirs() ) + { + if( not -d $dir ) + { + Debug('Creating directory: ' . $dir); + mkdir( $dir ) or + Error('Cannot create directory: ' . + $dir . ': ' . $!); + chown( $uid, $gid, $dir ) or + Error('Cannot change ownership for ' . + $dir . ': ' . $!); + chmod( 02755, $dir ) or + Error('Cannot chmod 02755 for ' . + $dir . ': ' . $!); + } + } + + if( $workerThreads > 1 ) + { + $confBuildSemaphore->up(); + } + } + else + { + Error('Skipping mkdir because of errors'); + } + } + + return $ok; +} + + +sub removeFromBundle +{ + my $outfile = shift; + + my $relname = relXmlFilename($outfile); + + my $removeFromBundle = 1; + + if( $forcebundle ) + { + if( defined( $fallback ) and + -e $outfile and -M $outfile <= $fallback ) + { + Warn('Falling back to the old version of ' . $relname); + $removeFromBundle = 0; + } + $everythingsOk = 1; + } + + if( $removeFromBundle ) + { + foreach my $bundleName ( sort keys %outputBundles ) + { + if( exists( $outputBundles{$bundleName}{$relname} ) ) + { + delete $outputBundles{$bundleName}{$relname}; + Warn('Bundle ' . $bundleName . ' will not have ' . + $relname . ' included because of errors'); + } + } + } +} + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/flushmonitors.in b/torrus/bin/flushmonitors.in new file mode 100644 index 000000000..6c01269ac --- /dev/null +++ b/torrus/bin/flushmonitors.in @@ -0,0 +1,143 @@ +#!@PERL@ -w +# Copyright (C) 2010 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: flushmonitors.in,v 1.1 2010-12-27 00:04:01 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +BEGIN { require '@torrus_config_pl@'; } + +use Getopt::Long; +use strict; + +use Torrus::SiteConfig; +use Torrus::ConfigTree; +use Torrus::Log; + +exit(1) if not Torrus::SiteConfig::verify(); + +our @trees; +our $all_trees; + +our $debug; +our $verbose; +our $help_needed; + +my $ok = GetOptions ('tree=s' => \@trees, + 'all' => \$all_trees, + 'debug' => \$debug, + 'verbose' => \$verbose, + 'help' => \$help_needed); + +if( not $ok or not (scalar(@trees) or $all_trees) or + $help_needed or scalar(@ARGV) > 0 ) +{ + print STDERR "Usage: $0 --tree=NAME [options...]\n", + "The utility flushes all monitor alarms and dynamic tokenset members\n", + "Options:\n", + " --tree=NAME tree name(s) to flush\n", + " --all flush all trees\n", + " --debug set the log level to debug\n", + " --verbose set the log level to info\n", + " --help this help message\n"; + exit 1; +} + +if( $all_trees ) +{ + @trees = Torrus::SiteConfig::listTreeNames(); +} + +if( $debug ) +{ + Torrus::Log::setLevel('debug'); +} +elsif( $verbose ) +{ + Torrus::Log::setLevel('verbose'); +} + + +&Torrus::DB::setSafeSignalHandlers(); + +Verbose(sprintf('Torrus version %s', '@VERSION@')); + +foreach my $tree ( @trees ) +{ + if( not Torrus::SiteConfig::treeExists( $tree ) ) + { + Error("Tree named \"" . $tree . "\" does not exist"); + exit(1); + } + + &Torrus::DB::checkInterrupted(); + + Verbose("Flushing alarms and tokensets for the tree: $tree"); + + my $config_tree = new Torrus::ConfigTree( -TreeName => $tree, + -Wait => 1 ); + if( not defined( $config_tree ) ) + { + next; + } + + my $db = new Torrus::DB('monitor_alarms', + -Subdir => $tree, + -WriteAccess => 1); + + + my $cursor = $db->cursor(-Write => 1); + while( my ($key, $timers) = $db->next($cursor) ) + { + Debug('Deleting alarm: ' . $key); + $db->c_del( $cursor ); + + } + undef $cursor; + undef $db; + + &Torrus::DB::checkInterrupted(); + + my @members; + foreach my $ts ( $config_tree->getTsets() ) + { + Debug('Processing tokenset: ' . $ts); + + foreach my $member ( $config_tree->tsetMembers( $ts ) ) + { + my $origin = $config_tree->tsetMembers( $ts, $member ); + + if( not defined( $origin ) or $origin ne 'static' ) + { + my $path = $config_tree->path($member); + $config_tree->tsetDelMember($ts, $member); + Verbose('deleted ' . $path . ' from tokenset: ' . $ts); + } + } + } + + undef $config_tree; + &Torrus::DB::cleanupEnvironment(); +} + +exit; + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/genddx.in b/torrus/bin/genddx.in new file mode 100644 index 000000000..6e3464e66 --- /dev/null +++ b/torrus/bin/genddx.in @@ -0,0 +1,255 @@ +#!@PERL@ +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: genddx.in,v 1.1 2010-12-27 00:04:00 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +# Generate the SNMP discovery instructions XML file out of plaintext +# list of hosts. + +BEGIN { require '@devdiscover_config_pl@'; } + +use strict; +use Getopt::Long; +use XML::LibXML; + +use Torrus::Log; + +our $outFormatVersion = '1.0'; + +our @hosts = (); +our $hostfile; + +our %globalParams = + ( + 'output-file' => 'routers.xml', + 'domain-name' => '', + 'host-subtree' => '/Routers', + 'snmp-port' => '161', + 'snmp-community' => 'public', + 'snmp-version' => '2c', + 'snmp-timeout' => 10, + 'snmp-retries' => 2, + 'rrd-hwpredict' => 0, + 'data-dir' => '@defrrddir@', + ); + +our $outfile = 'routers.ddx'; + + +my $creator = "Torrus version @VERSION@\n" . + "This file was generated by command:\n" . + $0 . " \\\n"; +foreach my $arg ( @ARGV ) +{ + if( $arg =~ /^--/ ) + { + $creator .= ' ' . $arg . ' '; + } + else + { + $creator .= "\'" . $arg . "\'\\\n"; + } +} +$creator .= "\nOn " . scalar(localtime(time)); + +my $ok = GetOptions( + 'host=s' => \@hosts, + 'hostfile=s' => \$hostfile, + 'out=s' => \$outfile, + 'discout=s' => \$globalParams{'output-file'}, + 'domain=s' => \$globalParams{'domain-name'}, + 'version=s' => \$globalParams{'snmp-version'}, + 'community=s' => \$globalParams{'snmp-community'}, + 'port=i' => \$globalParams{'snmp-port'}, + 'timeout=i' => \$globalParams{'snmp-timeout'}, + 'retries=i' => \$globalParams{'snmp-retries'}, + 'subtree=s' => \$globalParams{'host-subtree'}, + 'holtwinters' => \$globalParams{'rrd-hwpredict'}, + 'datadir=s' => \$globalParams{'data-dir'}, + ); + +if( not $ok or + ( not $hostfile and scalar(@hosts) == 0 ) or + scalar( @ARGV ) > 0 ) +{ + print STDERR "Generate devdiscover XML configuration\n"; + + print STDERR "Usage: $0 options...\n", + "Options:\n", + " --host=hostname router hostname\n", + " --hostfile=filename space-separated router hostnames file\n", + " --out=filename output file [".$outfile."]\n", + + " --discout=filename discovery output file\n", + " [", $globalParams{'output-file'}, "]\n", + + " --domain=domain optional DNS domain name\n", + + " --version=v SNMP version [", + $globalParams{'snmp-version'}, "]\n", + + " --community=string SNMP read community [", + $globalParams{'snmp-community'}, "]\n", + + " --port=number SNMP port [", + $globalParams{'snmp-port'}, "]\n", + + " --retries=number SNMP retries [", + $globalParams{'snmp-retries'}, "]\n", + + " --timeout=number SNMP timeout [", + $globalParams{'snmp-timeout'}, "]\n", + + " --subtree=string Subtree name [", + $globalParams{'host-subtree'}, "]\n", + + " --datadir=path data-dir parameter [", + $globalParams{'data-dir'}, "]\n", + + " --holtwinters Enable Holt-Winters analysis\n", + "\n", + "Host names may be of form \"host:devname\" where devname is a symbolic\n", + "device name.\n", + "Output file is placed into " . $Torrus::Global::discoveryDir, + "\n if no path is given.\n"; + exit 1; +} + +# Place the output file in discovery directory if the path is not given +if( $outfile !~ /\// ) +{ + $outfile = $Torrus::Global::discoveryDir . '/' . $outfile; +} + +# Convert flags from true/false to yes/no +foreach my $param ( 'rrd-hwpredict' ) +{ + if( $globalParams{$param} ) + { + $globalParams{$param} = 'yes'; + } + else + { + $globalParams{$param} = 'no'; + } +} + +if( $globalParams{'host-subtree'} !~ /^\/[0-9A-Za-z_\-\.\/]*$/ or + $globalParams{'host-subtree'} =~ /\.\./ ) +{ + Error("Invalid format for subtree name: " . $globalParams{'host-subtree'}); + exit 1; +} + +if( defined $hostfile ) +{ + if( not open(HOSTS, $hostfile) ) + { + print STDERR "Cannot open $hostfile: $!"; + exit 1; + } + while(<HOSTS>) + { + s/^\s+//; + s/\s+$//; + push( @hosts, split( /\s+/ ) ); + } +} + +# Create XML DOM + +my $doc = XML::LibXML->createDocument( "1.0", "UTF-8" ); +my $root = $doc->createElement('snmp-discovery'); +$doc->setDocumentElement( $root ); + +{ + my $fileInfoNode = $doc->createElement('file-info'); + $root->appendChild( $fileInfoNode ); + + my $formatNode = $doc->createElement('format-version'); + $formatNode->appendText( $outFormatVersion ); + $fileInfoNode->appendChild( $formatNode ); +} + +{ + my $creatorNode = $doc->createElement('creator-info'); + $creatorNode->appendText( $creator ); + $root->appendChild( $creatorNode ); +} + +createParamsDom( \%globalParams, $doc, $root ); + + +foreach my $host ( @hosts ) +{ + my $devname = $host; + if( $host =~ /([^:]+):(.+)/ ) + { + $host = $1; + $devname = $2; + } + + my $hostNode = $doc->createElement('host'); + $root->appendChild( $hostNode ); + + my %hostParams = ( 'snmp-host' => $host ); + if( $devname ne $host ) + { + $hostParams{'symbolic-name'} = $devname; + } + + createParamsDom( \%hostParams, $doc, $hostNode ); +} + +my $ok = $doc->toFile( $outfile, 2 ); +if( $ok ) +{ + print STDERR ("Wrote $outfile\n"); +} +else +{ + print STDERR ("Cannot write $outfile: $!\n"); +} + + +exit($ok ? 0:1); + + +sub createParamsDom +{ + my $params = shift; + my $doc = shift; + my $parentNode = shift; + + foreach my $param ( sort keys %{$params} ) + { + my $paramNode = $doc->createElement('param'); + $paramNode->setAttribute( 'name', $param ); + $paramNode->setAttribute( 'value', $params->{$param} ); + $parentNode->appendChild( $paramNode ); + } +} + + + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/genlist.in b/torrus/bin/genlist.in new file mode 100644 index 000000000..2b79fc126 --- /dev/null +++ b/torrus/bin/genlist.in @@ -0,0 +1,197 @@ +#!@PERL@ +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: genlist.in,v 1.1 2010-12-27 00:04:01 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +BEGIN { require '@torrus_config_pl@'; } + +use strict; +use Getopt::Long; + +use Torrus::Log; +use Torrus::ConfigTree; +use Torrus::SiteConfig; + +exit(1) if not Torrus::SiteConfig::verify(); + +my $tree; +my $initPath = '/'; +my $listWhat = 'rrdfiles'; +my $selectType = 'all'; + +my $help_needed; + +my %listingsSupported = + ( + 'rrdfiles' => { + 'collector' => 1, + 'readonly' => 1, + 'all' => 1, + }, + + 'snmphosts' => { + 'collector' => 1, + }, + ); + +my $ok = GetOptions ('tree=s' => \$tree, + 'path=s' => \$initPath, + 'what=s' => \$listWhat, + 'type=s' => \$selectType, + 'help' => \$help_needed); + +if( not $ok or not $tree or $help_needed or + not $listingsSupported{$listWhat}{$selectType} or scalar(@ARGV) > 0 ) +{ + print STDERR "Usage: $0 --tree=NAME [options...]\n", + "Options:\n", + " --tree=NAME tree name\n", + " --path=/PATH [".$initPath."] subtree name\n", + " --what=WHAT [".$listWhat."] what to list\n", + " Supported listings:\n", + " rrdfiles List RRD file paths\n", + " snmphosts List SNMP hosts\n", + " --type=TYPE [".$selectType."] selection type\n", + " Supported types:\n", + " collector Collector leaves\n", + " readonly Read-only leaves\n", + " all All of above\n", + " --help this help message\n"; + exit 1; +} + + +if( not Torrus::SiteConfig::treeExists( $tree ) ) +{ + Error('Tree ' . $tree . ' does not exist'); + exit 1; +} + +&Torrus::DB::setSafeSignalHandlers(); + +my $config_tree = new Torrus::ConfigTree( -TreeName => $tree, -Wait => 1 ); +if( not defined( $config_tree ) ) +{ + exit 1; +} + +my $initToken = $config_tree->token( $initPath ); +if( not defined( $initToken ) ) +{ + Error('No such subtree: ' . $initPath); + exit 1; +} + +my $listing = {}; + +my $listParams = {}; +if( $selectType eq 'all' ) +{ + foreach my $type ( keys %{$listingsSupported{$listWhat}} ) + { + if( $type ne 'all' ) + { + $listParams->{$type} = 1; + } + } +} +else +{ + $listParams->{$selectType} = 1; +} + +pickup_data( $config_tree, $initToken, $listing, $listWhat, $listParams ); + +foreach my $item ( sort keys %{$listing} ) +{ + print $item, "\n"; +} + +exit 0; + +sub pickup_data +{ + my $config_tree = shift; + my $token = shift; + my $listing = shift; + my $listWhat = shift; + my $listParams = shift; + + foreach my $ctoken ( $config_tree->getChildren( $token ) ) + { + &Torrus::DB::checkInterrupted(); + + if( $config_tree->isSubtree( $ctoken ) ) + { + pickup_data( $config_tree, $ctoken, + $listing, $listWhat, $listParams ); + } + elsif( $config_tree->isLeaf( $ctoken ) ) + { + if( $listWhat eq 'rrdfiles' and + ( + ( + $listParams->{'collector'} and + $config_tree->getNodeParam( $ctoken, 'ds-type' ) eq + 'collector' and + $config_tree->getNodeParam( $ctoken, 'storage-type' ) eq + 'rrd' + ) or + ( + $listParams->{'readonly'} and + $config_tree->getNodeParam( $ctoken, 'ds-type' ) eq + 'rrd-file' and + $config_tree->getNodeParam( $ctoken, 'leaf-type' ) eq + 'rrd-def' + ) + ) + ) + { + my $datafile = + $config_tree->getNodeParam( $ctoken, 'data-file' ); + my $datadir = + $config_tree->getNodeParam( $ctoken, 'data-dir' ); + $listing->{$datadir . '/' . $datafile} = 1; + } + elsif( $listWhat eq 'snmphosts' and + $listParams->{'collector'} and + $config_tree->getNodeParam( $ctoken, 'ds-type' ) eq + 'collector' ) + { + my $host = + $config_tree->getNodeParam( $ctoken, 'snmp-host' ); + my $oid = + $config_tree->getNodeParam( $ctoken, 'snmp-object' ); + + if( defined( $host ) and length( $host ) > 0 and + defined( $oid ) and length( $oid ) > 0 ) + { + $listing->{$host} = 1; + } + } + } + } +} + + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/genreport.in b/torrus/bin/genreport.in new file mode 100644 index 000000000..6d21b4878 --- /dev/null +++ b/torrus/bin/genreport.in @@ -0,0 +1,181 @@ +#!@PERL@ +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: genreport.in,v 1.1 2010-12-27 00:04:01 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +# Collect the router information and create the XML file + +BEGIN { require '@torrus_config_pl@'; } + +use strict; +use Getopt::Long; + +use Torrus::Log; +use Torrus::ReportOutput::HTML; +use Torrus::SiteConfig; + +my $report; +my $date; +my $time = '00:00'; +my $genhtml; +my @trees; +my $all2tree; + +my $debug = 0; +my $verbose = 0; + +my $ok = GetOptions( + 'report=s' => \$report, + 'date=s' => \$date, + 'time=s' => \$time, + 'genhtml' => \$genhtml, + 'tree=s' => \@trees, + 'all2tree=s' => \$all2tree, + 'verbose' => \$verbose, + 'debug' => \$debug + ); + +if( $report and not defined($Torrus::ReportGenerator::modules{$report}) ) +{ + print STDERR "Unknown report name: ", $report, "\n\n"; + $ok = 0; +} + +if( not $ok or (not $report and not $genhtml) or + ($report and not $date) or + ($genhtml and scalar(@trees) > 0 and $all2tree) or + scalar( @ARGV ) > 0 ) +{ + print STDERR + "Usage: $0 --report=ReportName --date=YYYY-MM-DD | ", + "--genhtml options...\n"; + print STDERR "Options:\n", + " --report=ReportName Report name.\n", + " --date=YYYY-MM-DD Report start date. ", + "For monthly reports, 1st day in a month.\n", + " --time=hh:mm Report start time. Ignored for monthly reports\n", + " --genhtml Generate HTML output from the database\n", + " --tree=TREE Generate HTML for a given tree only\n", + " --all2tree=TREE Generate reports for all service IDs and place\n", + " into the given tree (excludes the option --tree)\n", + " --verbose print extra information\n", + " --debug print debugging information\n", + "\n", + "Report names supported:\n"; + + foreach my $rep ( sort keys %Torrus::ReportGenerator::modules ) + { + print STDERR " ", $rep, "\n"; + } + print STDERR "\n"; + + exit 1; +} + +if( $debug ) +{ + Torrus::Log::setLevel('debug'); +} +elsif( $verbose ) +{ + Torrus::Log::setLevel('verbose'); +} + +&Torrus::DB::setSafeSignalHandlers(); + +if( $report ) +{ + my $class = $Torrus::ReportGenerator::modules{$report}; + eval( 'require ' . $class ); + die( $@ ) if $@; + + my $generator = $class->new({ + 'Name' => $report, + 'Date' => $date, + 'Time' => $time}); + + if( defined( $generator ) ) + { + $generator->generate(); + } + else + { + $ok = 0; + } +} + +if( $genhtml ) +{ + if( $all2tree ) + { + push( @trees, $all2tree ); + } + + if( scalar( @trees ) == 0 ) + { + @trees = Torrus::SiteConfig::listTreeNames(); + } + else + { + foreach my $tree ( @trees ) + { + if( not Torrus::SiteConfig::treeExists( $tree ) ) + { + Error('Tree ' . $tree . ' does not exist'); + $ok = 0; + } + } + } + + if( $ok ) + { + foreach my $tree ( @trees ) + { + &Torrus::DB::checkInterrupted(); + + Verbose('Generating HTML report for tree ' . $tree); + + my $options = {'Tree' => $tree}; + + if( length( $all2tree ) > 0 ) + { + $options->{'All_Service_IDs'} = 1; + } + + my $out = new Torrus::ReportOutput::HTML( $options ); + + if( $out->init() ) + { + $ok = $out->generate() ? $ok:0; + } + else + { + $ok = 0; + } + } + } +} + +exit($ok ? 0:1); + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/install_plugin.in b/torrus/bin/install_plugin.in new file mode 100644 index 000000000..31b44e730 --- /dev/null +++ b/torrus/bin/install_plugin.in @@ -0,0 +1,51 @@ +#!@SHELL@ +# Copyright (C) 2004 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: install_plugin.in,v 1.1 2010-12-27 00:04:00 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> +# + +# Torrus plugin installation utility + +plugin=$1 +shift + +if test -z "$plugin"; then + echo "Usage: $0 plugin_dir [options...]" 1>&2 + exit 1 +fi + +if test ! -d $plugin; then + echo "No such directory: $plugin" 1>&2 + exit 1 +fi + +echo Installing Torrus plugin from $plugin + +cd $plugin +eval './configure '`cat @cfgdefdir@/instvars`' '$@ || exit 1 +make || exit 1 +make install || exit 1 + +echo Plugin installation finished + + +# Local Variables: +# mode: shell-script +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/monitor.in b/torrus/bin/monitor.in new file mode 100644 index 000000000..c8579997b --- /dev/null +++ b/torrus/bin/monitor.in @@ -0,0 +1,176 @@ +#!@PERL@ +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: monitor.in,v 1.1 2010-12-27 00:04:03 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +BEGIN { require '@torrus_config_pl@'; } + +use strict; +use Proc::Daemon; +use Getopt::Long; + +use Torrus::Log; +use Torrus::Monitor; +use Torrus::SiteConfig; + +exit(1) if not Torrus::SiteConfig::verify(); + +our $tree; +our $nodaemon; +our $runonce; +our $delay = 0; +our $debug; +our $verbose; +our $help_needed; + +# Derive the process name from the command line +our $process_name = $0; +$process_name =~ s/^.*\/([^\/]+)$/$1/; +$process_name .= ' ' . join(' ', @ARGV); + + +my $ok = GetOptions ('tree=s' => \$tree, + 'nodaemon' => \$nodaemon, + 'runonce' => \$runonce, + 'delay=i' => \$delay, + 'debug' => \$debug, + 'verbose' => \$verbose, + 'help' => \$help_needed); + +if( not $ok or not $tree or $help_needed or scalar(@ARGV) > 0 ) +{ + print STDERR "Usage: $0 --tree=NAME [options...]\n", + "Options:\n", + " --tree=NAME tree name\n", + " --nodaemon do not fork daemon and log to STDERR\n", + " --runonce run one time and exit. Implies --nodaemon\n", + " --delay delay the start of the first cycle, minutes\n", + " --debug set the log level to debug\n", + " --verbose set the log level to info\n", + " --help this help message\n"; + exit 1; +} + +if( not Torrus::SiteConfig::mayRunMonitor( $tree ) ) +{ + Error('Tree ' . $tree . ' is not configured to run monitor'); + exit 1; +} + + +if( $debug ) +{ + Torrus::Log::setLevel('debug'); +} +elsif( $verbose ) +{ + Torrus::Log::setLevel('verbose'); +} + +my $logfile = $Torrus::Global::logDir . '/monitor.' . $tree . '.log'; +my $pidfile; + +my $rotateLogs = sub +{ + Info('Caught SIGHUP. Reopening log file'); + close( STDERR ); + open( STDERR, ">>$logfile" ); +}; + +if( not $nodaemon and not $runonce ) +{ + my $pidfilename = + $Torrus::Global::pidDir . '/monitor.' . $tree . '.pid'; + + if( -r $pidfilename ) + { + Error("Another monitor daemon is running, pid=", + `cat $pidfilename`); + exit 1; + } + + &Proc::Daemon::Init(); + umask 0017; # Proc::Daemon::Init sets the mask to all-writable + + $SIG{'HUP'} = $rotateLogs; + + # At this point, we cannot tell anyone if "open" fails + open(STDERR, ">>$logfile"); + + $pidfile = $pidfilename; + + if( open( PID, ">$pidfile" ) ) + { + printf PID ( "%d", $$ ); + close PID; + } + else + { + Error("Cannot open $pidfile for writing: $!"); + } +} + +Info(sprintf("Torrus version %s", '@VERSION@')); +Info(sprintf("%s started for tree %s", $0, $tree)); +Debug(sprintf("Process ID %d", $$)); + +if( $delay > 0 ) +{ + Info(sprintf('Delaying for %d minutes', $delay)); + sleep($delay * 60); +} + +&Torrus::DB::setSafeSignalHandlers(); + +my %options = + ( + '-ProcessName' => $process_name, + '-Tree' => $tree, + '-Delay' => $delay + ); +if( $runonce ) +{ + $options{'-RunOnce'} = 1; +} + +my $scheduler = new Torrus::MonitorScheduler( %options ); +$scheduler->run(); + +if( not $options{'-RunOnce'} ) +{ + Error("Monitor process exited: nothing to collect"); + unlink $pidfile; +} + +exit; + + +END +{ + if( defined($pidfile) and -r $pidfile ) + { + unlink $pidfile; + } +} + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/nodeid.in b/torrus/bin/nodeid.in new file mode 100644 index 000000000..b362a955b --- /dev/null +++ b/torrus/bin/nodeid.in @@ -0,0 +1,252 @@ +#!@PERL@ -w +# Copyright (C) 2010 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: nodeid.in,v 1.1 2010-12-27 00:04:03 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +BEGIN { require '@torrus_config_pl@'; } + +use strict; +use Getopt::Long; +use JSON; +use File::Copy; + +use Torrus::ConfigTree; +use Torrus::SiteConfig; +use Torrus::Renderer; +use Torrus::Log; + +exit(1) if not Torrus::SiteConfig::verify(); + + +my %commands = + ('info' => \&do_info, + 'search' => \&do_search, + 'render' => \&do_render); + + + +my $tree; +my $cmd; + +my $nodeid; +my $print_details; +my $search_prefix; +my $search_substring; +my $render_view; +my $render_out; + + +my $help_needed; + + +my $ok = GetOptions('tree=s' => \$tree, + 'cmd=s' => \$cmd, + 'nodeid=s' => \$nodeid, + 'details' => \$print_details, + 'prefix=s' => \$search_prefix, + 'substring=s' => \$search_substring, + 'view=s' => \$render_view, + 'out=s' => \$render_out, + 'help' => \$help_needed); + +if( not $ok or + not $tree or not $cmd or not $commands{$cmd} or + ( ($cmd eq 'info' or $cmd eq 'render') and not $nodeid ) or + ( $cmd eq 'search' and not ($search_prefix or $search_substring) ) or + $help_needed or scalar(@ARGV) > 0 ) +{ + print STDERR "Usage: $0 --tree=NAME --cmd=CMD [options...]\n", + "Options:\n", + " --tree=NAME tree name\n", + " --cmd=CMD Command (info|search|render)\n", + " --nodeid=NODEID nodeid (mandatory for info and render)\n", + " --details print nodeid details (valid with info and search)\n", + " --prefix=STR search prefix\n", + " --substring=STR search substring\n", + " --view=VIEW render view (optional)\n", + " --out=FILE render output\n", + " --help this help message\n"; + exit 1; +} + + +if( not Torrus::SiteConfig::treeExists( $tree ) ) +{ + Error('Tree ' . $tree . ' does not exist'); + exit 1; +} + + +&Torrus::DB::setSafeSignalHandlers(); + +{ + my $config_tree = new Torrus::ConfigTree( -TreeName => $tree ); + if( not defined($config_tree) ) + { + Error("Configuration is not ready"); + exit 1; + } + + if( $cmd eq 'info' or $cmd eq 'render' ) + { + my $token = $config_tree->getNodeByNodeid($nodeid); + if( not defined( $token ) ) + { + Error('nodeid not found: ' . $nodeid); + exit(1); + } + + if( $cmd eq 'info' ) + { + print_nodeid($config_tree, [$token], $print_details); + } + else + { + render_node($config_tree, $token, $render_view, $render_out); + } + } + elsif( $cmd eq 'search' ) + { + my $results; + if( defined($search_prefix) ) + { + $results = $config_tree->searchNodeidPrefix($search_prefix); + } + else + { + $results = $config_tree->searchNodeidSubstring($search_substring); + } + + if( defined( $results ) and scalar(@{$results}) > 0 ) + { + my $tokens = []; + # results are pairs [nodeid,token] + foreach my $res ( @{$results} ) + { + push(@{$tokens}, $res->[1]); + } + print_nodeid($config_tree, $tokens, $print_details); + } + else + { + print STDERR "Nothing found\n"; + exit(1); + } + } + else + { + printf STDERR ("Unknown command: %s\n", $cmd); + exit(1); + } +} + +exit(0); + + +sub print_nodeid +{ + my $config_tree = shift; + my $tokens = shift; + my $details = shift; + + my $json = new JSON; + $json->pretty(); + $json->canonical(); + + my @all; + + foreach my $token ( @{$tokens} ) + { + my $info = { + 'nodeid' => $config_tree->getNodeParam($token, 'nodeid', 1), + }; + + if( $details ) + { + $info->{'path'} = $config_tree->path($token); + $info->{'is_leaf'} = $config_tree->isLeaf($token) ? 1:0; + $info->{'tree'} = $config_tree->treeName(); + if( $info->{'is_leaf'} ) + { + my $dsType = $config_tree->getNodeParam( $token, 'ds-type' ); + $info->{'param:ds-type'} = $dsType; + if( $dsType eq 'collector' ) + { + foreach my $param + ('collector-type', 'collector-period', + 'storage-type', 'data-file', 'data-dir', 'rrd-ds', + 'ext-service-id', + 'snmp-host', 'domain-name', 'snmp-object') + { + my $val = $config_tree->getNodeParam($token, $param); + + if( defined( $val ) ) + { + $info->{'param:' . $param} = $val; + } + } + } + } + } + + push(@all, $info); + } + + print $json->encode(\@all); +} + + + +sub render_node +{ + my $config_tree = shift; + my $token = shift; + my $view = shift; + my $out = shift; + + my $r = new Torrus::Renderer; + + my($fname, $mimetype) = $r->render($config_tree, $token, $view); + + if( defined($out) ) + { + if( not copy( $fname, $out ) ) + { + printf STDERR ("Failed to write to %s: %s\n", $out, $!); + exit(1); + } + + $fname = $out; + } + + my $json = new JSON; + $json->pretty(); + + print $json->encode({'Content-type' => $mimetype, + 'Filename' => $fname}); +} + + + + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/rrddir2xml.in b/torrus/bin/rrddir2xml.in new file mode 100644 index 000000000..c82fcf871 --- /dev/null +++ b/torrus/bin/rrddir2xml.in @@ -0,0 +1,311 @@ +#!@PERL@ +# Copyright (C) 2002 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: rrddir2xml.in,v 1.1 2010-12-27 00:04:01 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +# Generate Torrus XML configuration from a directory containing RRD files +# + +BEGIN { require '@devdiscover_config_pl@'; } + +use strict; +use Getopt::Long; +use IO::Dir; +use Fcntl qw(:mode); +use RRDs; + +use Torrus::ConfigBuilder; +use Torrus::Log; + + +my $creator = "Torrus version @VERSION@\n" . + "This file was generated by command:\n" . + $0 . " \\\n"; +foreach my $arg ( @ARGV ) +{ + if( $arg =~ /^--/ ) + { + $creator .= ' ' . $arg . ' '; + } + else + { + $creator .= "\'" . $arg . "\'\\\n"; + } +} +$creator .= "\nOn " . scalar(localtime(time)); + + +my $indir; +my $recursive = 0; +my $filter = '.*'; +my $outfile = 'rrddir.xml'; +my $topsubtree = '/'; +my $splitexpr = '_+'; +my $levels = 2; +my $hwpredict = 0; +my $comment; +my $debug = 0; +my $verbose = 0; + + +my $ok = GetOptions( + 'dir=s' => \$indir, + 'recursive' => \$recursive, + 'filter=s' => \$filter, + 'out=s' => \$outfile, + 'subtree=s' => \$topsubtree, + 'split=s' => \$splitexpr, + 'levels=i' => \$levels, + 'comment=s' => \$comment, + 'holtwinters' => \$hwpredict, + 'verbose' => \$verbose, + 'debug' => \$debug + ); + +if( not $ok or not $indir or scalar( @ARGV ) > 0 ) +{ + print STDERR + "Generate Torrus XML configuration from a directory with RRD files\n"; + + print STDERR "Usage: $0 --dir=path options...\n", + "Options:\n", + " --dir=path directory to read RRD files from\n", + " --recursive read the directories recursively\n", + " --filter=re filter RE for file and directory names\n", + " --out=filename output file [".$outfile."]\n", + " --subtree=subtree XML config subtree [".$topsubtree."]\n", + " --split=regexp regexp to split file names [".$splitexpr."]\n", + " --levels=integer no. of subtree levels [".$levels."]\n", + " --comment=text top subtree comment\n", + " --holtwinters enable Holt-Winters boundaries diaplay\n", + " --verbose print extra information\n", + " --debug print debugging information\n"; + + exit 1; +} + +if( $debug ) +{ + Torrus::Log::setLevel('debug'); +} +elsif( $verbose ) +{ + Torrus::Log::setLevel('verbose'); +} + +if( not -d $indir ) +{ + Error('No such directory: ' . $indir); + exit 1; +} + +if( $indir !~ /^\// ) +{ + Error('Input directory must be an absolute path: ' . $indir); + exit 1; +} + +# remove trailing slash from $indir +$indir =~ s/\/$//; + +if( $topsubtree !~ /^\/[0-9A-Za-z_\-\.\/]*$/ or + $topsubtree =~ /\.\./ ) +{ + Error("Invalid format for subtree name: " . $topsubtree); + exit 1; +} + + +if( $outfile !~ /^\// ) +{ + $outfile = $Torrus::Global::siteXmlDir . '/' . $outfile; +} + +my %rrdinfos; +read_rrd_dir( \%rrdinfos, $indir, $filter, $recursive ); + +Verbose(sprintf('Found %d RRD files', scalar( keys( %rrdinfos ) ) )); + +my $cb = new Torrus::ConfigBuilder; +$cb->addCreatorInfo( $creator ); + +# Chop the first and last slashes +my $path = $topsubtree; +$path =~ s/^\///; +$path =~ s/\/$//; + +# generate subtree path XML +my $topSubtreeNode = undef; +foreach my $subtreeName ( split( '/', $path ) ) +{ + $topSubtreeNode = $cb->addSubtree( $topSubtreeNode, $subtreeName ); +} + +if( length( $comment ) > 0 ) +{ + $cb->addParam( $topSubtreeNode, 'comment', $comment ); +} + +foreach my $rrdfile ( sort keys %rrdinfos ) +{ + my @nameparts = split( $splitexpr, $rrdfile, $levels ); + + my $subtreeNode = $topSubtreeNode; + foreach my $subtreeName ( @nameparts ) + { + $subtreeNode = $cb->addSubtree( $subtreeNode, $subtreeName ); + } + + my $info = $rrdinfos{$rrdfile}; + + my $legend = + 'Directory:' . $info->{'dir'} . ';' . + 'File:' . $rrdfile . ';'; + + $cb->addParam( $subtreeNode, 'legend', $legend ); + + my %dsnames; + my $this_rrd_hwpredict = 0; + + foreach my $prop ( keys %{$info->{'rrdinfo'}} ) + { + if( $prop =~ /^ds\[(\S+)\]\./o ) + { + $dsnames{$1} = 1; + } + else + { + if( $prop =~ /^rra\[\d+\]\.cf/o and + $info->{'rrdinfo'}->{$prop} eq 'FAILURES' ) + { + $this_rrd_hwpredict = 1; + } + } + } + + if( not $hwpredict ) + { + $this_rrd_hwpredict = 0; + } + + foreach my $dsname ( sort keys %dsnames ) + { + my $dslegend = $legend . 'DS:' . $dsname . ';Type:' . + $info->{'rrdinfo'}->{'ds['.$dsname.'].type'}; + + my $params = { + 'legend' => $dslegend, + 'ds-type' => 'rrd-file', + 'leaf-type' => 'rrd-def', + 'rrd-cf' => 'AVERAGE', + 'data-file' => $rrdfile, + 'data-dir' => $info->{'dir'}, + 'rrd-ds' => $dsname, + 'rrd-hwpredict' => ($this_rrd_hwpredict ? 'enabled':'disabled') + }; + + $cb->addLeaf( $subtreeNode, $dsname, $params ); + } +} + +my $ok = $cb->toFile( $outfile ); +if( $ok ) +{ + Verbose('Wrote ' . $outfile); +} +else +{ + Error('Cannot write ' . $outfile . ': ' . $!); +} + +exit( $ok ? 0:1); + + + +sub read_rrd_dir +{ + my $infos = shift; + my $indir = shift; + my $filter = shift; + my $recursive = shift; + + Debug('Reading directory: ' . $indir); + + my @subdirs; + + my %dir; + tie( %dir, 'IO::Dir', $indir ); + + foreach my $file ( keys %dir ) + { + if( $file =~ /^\./ or $file !~ $filter ) + { + Debug('Skipping ' . $file); + next; + } + + my $mode = $dir{$file}->mode(); + if( S_ISDIR( $mode ) ) + { + Debug($file . ' is a directory'); + push( @subdirs, $file ); + } + elsif( S_ISREG( $mode ) ) + { + Debug($file . ' is a regular file'); + if( defined( $infos->{$file} ) ) + { + Warn("Duplicate file name: $file"); + } + else + { + my $fullname = $indir . '/' . $file; + my $rrdinfo = RRDs::info( $fullname ); + my $err = RRDs::error(); + if( $err ) + { + Verbose($fullname . ' is not an RRD file'); + } + else + { + Debug('Found RRD file: ' . $file); + $infos->{$file}->{'fullname'} = $fullname; + $infos->{$file}->{'dir'} = $indir; + $infos->{$file}->{'rrdinfo'} = $rrdinfo; + } + } + } + } + + untie %dir; + + if( $recursive and scalar( @subdirs ) > 0 ) + { + foreach my $subdir ( @subdirs ) + { + read_rrd_dir( $infos, $indir . '/' . $subdir, + $filter, $recursive ); + } + } +} + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/schedulerinfo.in b/torrus/bin/schedulerinfo.in new file mode 100644 index 000000000..42515b014 --- /dev/null +++ b/torrus/bin/schedulerinfo.in @@ -0,0 +1,454 @@ +#!@PERL@ -w +# Copyright (C) 2003 Stanislav Sinyagin +# Copyright (C) 2003 Christian Schnidrig +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: schedulerinfo.in,v 1.1 2010-12-27 00:04:00 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +BEGIN { require '@torrus_config_pl@'; } + +use strict; +use Getopt::Long; + +use Torrus::ConfigTree; +use Torrus::SiteConfig; +use Torrus::SchedulerInfo; +use Torrus::Log; + +exit(1) if not Torrus::SiteConfig::verify(); + +my $tree; +my $report_config; +my $report_runtime; +my $clear_treestats; + +my $help_needed; + + +my $ok = GetOptions('tree=s' => \$tree, + 'config' => \$report_config, + 'runtime' => \$report_runtime, + 'clear' => \$clear_treestats, + 'help' => \$help_needed); + +if( not $ok or + not $tree or + not ( $report_config or $report_runtime or $clear_treestats ) or + $help_needed or scalar(@ARGV) > 0 ) +{ + print STDERR "Usage: $0 --tree=NAME [options...]\n", + "Options:\n", + " --tree=NAME tree name\n", + " --config report scheduler configuration\n", + " --runtime report scheduler runtime statistics\n", + " --clear clear scheduler statistics for specific tree\n", + " --help this help message\n"; + exit 1; +} + + +if( not Torrus::SiteConfig::treeExists( $tree ) ) +{ + Error('Tree ' . $tree . ' does not exist'); + exit 1; +} + + +&Torrus::DB::setSafeSignalHandlers(); + +if( $clear_treestats ) +{ + my $stats = new Torrus::SchedulerInfo( -Tree => $tree, -WriteAccess => 1 ); + $stats->clearAll(); + print STDERR "Statistics cleared for tree $tree\n"; + exit 0; +} + +thickLine(); +printf("Torrus version %s\n", '@VERSION@'); +printf("Datasources tree: %s\n", $tree); +printf("Date: %s\n\n", scalar( localtime( time() ) ) ); + +if( $report_config ) +{ + my $config_tree = new Torrus::ConfigTree( -TreeName => $tree ); + if( not defined($config_tree) ) + { + Error("Configuration is not ready"); + exit 1; + } + + my $stats = { 'collectorLeaves' => {}, 'monitorLeaves' => 0 }; + + collectStats( $config_tree, $stats ); + + thickLine(); + printf("Scheduler configuration report\n\n"); + + foreach my $instance ( sort {$a<=>$b} keys %{$stats->{'collectorLeaves'}} ) + { + printf("Collector leaves for instance #%d: %d\n", + $instance, + $stats->{'collectorLeaves'}{$instance}); + } + + printf("Total monitor leaves: %d\n\n", $stats->{'monitorLeaves'}); + + printf("Scheduled leaves by type:\n"); + + foreach my $type ( sort keys %{$stats->{'leavesPerType'}} ) + { + printf(" %10s %-10d\n", $type, + $stats->{'leavesPerType'}{$type}); + } + printf("\n"); + + foreach my $instance ( sort {$a<=>$b} keys %{$stats->{'collectorLeaves'}} ) + { + if( $stats->{'collectorLeaves'}{$instance} > 0 ) + { + &Torrus::DB::checkInterrupted(); + + printf("Collector execution timeline for instance #%d:\n", + $instance); + reportTimeline( $stats->{'collectorSchedule'}{$instance} ); + } + } + + if( $stats->{'monitorLeaves'} > 0 ) + { + printf("Monitor execution timeline:\n"); + reportTimeline( $stats->{'monitorSchedule'} ); + } +} + +if( $report_runtime ) +{ + my @reportFormats = + ( + { 'label' => 'Running Time', + 'varname' => 'RunningTime' }, + + { 'label' => 'Late Start', + 'varname' => 'LateStart' }, + + { 'label' => 'Too Long', + 'varname' => 'TooLong' }, + + { 'label' => 'RRD Queue', + 'varname' => 'RRDQueue' }, + + { 'label' => 'Raw Queue', + 'varname' => 'RawQueue' } + + ); + + my @counterFormats = + ( + { 'label' => 'running cycles passed', + 'varname' => 'NTimesRunningTime' }, + + { 'label' => 'late starts', + 'varname' => 'NTimesLateStart' }, + + { 'label' => 'too long runs', + 'varname' => 'NTimesTooLong' }, + + { 'label' => 'overrun periods', + 'varname' => 'CountOverrunPeriods' }, + + { 'label' => 'missed periods', + 'varname' => 'CountMissedPeriods' } + ); + + my $sInfo = new Torrus::SchedulerInfo( '-Tree' => $tree ); + exit(1) if not defined( $sInfo ); + + my $stats = $sInfo->readStats(); + + thickLine(); + printf("Scheduler runtime report\n\n"); + + my $periodicTasks = {}; + foreach my $taskId ( keys %{$stats} ) + { + my ($type, $taskName, $instance, $period, $offset) = + split( ':', $taskId ); + if( $type eq 'P' ) + { + $periodicTasks->{$taskName}{$instance}{$period}{$offset} = $taskId; + } + } + + foreach my $taskName ( sort keys %{$periodicTasks} ) + { + foreach my $instance ( sort {$a<=>$b} + keys %{$periodicTasks->{$taskName}} ) + { + foreach my $period + ( sort {$a<=>$b} + keys %{$periodicTasks->{$taskName}{$instance}} ) + { + foreach my $offset + ( sort {$a<=>$b} + keys %{$periodicTasks->{$taskName}{$instance}{$period}} ) + { + &Torrus::DB::checkInterrupted(); + + my $taskId = + $periodicTasks->{$taskName}{$instance}{ + $period}{$offset}; + my $ref = $stats->{$taskId}; + + printf("Task: %s, Instance: %d, " . + "Period: %d seconds, Offset: %d seconds\n", + $taskName, $instance, $period, $offset); + + foreach my $format ( @counterFormats ) + { + if( defined( $ref->{$format->{'varname'}} ) ) + { + printf("%5d %s\n", + $ref->{$format->{'varname'}}, + $format->{'label'} ); + } + } + + thinLine(); + printf("%-15s%-10s%-10s%-10s%-10s\n", + '', 'Min', 'Max', 'Average', 'Exp Average'); + + foreach my $format ( @reportFormats ) + { + my $varname = $format->{'varname'}; + if( defined( $ref->{'Min' . $varname} ) ) + { + printf("%-15s%-10d%-10d%-10.1f%-10.1f\n", + $format->{'label'}, + $ref->{'Min' . $varname}, + $ref->{'Max' . $varname}, + $ref->{'Avg' . $varname}, + $ref->{'ExpAvg' . $varname}); + } + } + + thinLine(); + printf("\n"); + } + } + } + } +} + +thickLine(); +exit 0; + + +sub collectStats +{ + my $config_tree = shift; + my $stats = shift; + my $token = shift; + + if( not defined( $token ) ) + { + $token = $config_tree->token('/'); + } + + my @children = $config_tree->getChildren( $token ); + + foreach my $ctoken ( @children ) + { + &Torrus::DB::checkInterrupted(); + + if( $config_tree->isSubtree( $ctoken ) ) + { + collectStats( $config_tree, $stats, $ctoken ); + } + elsif( $config_tree->isLeaf( $ctoken ) ) + { + if( $config_tree->getNodeParam( $ctoken, 'ds-type' ) + eq 'collector' ) + { + my $instance = + $config_tree->getNodeParam + ( $ctoken, 'collector-instance' ); + + $stats->{'collectorLeaves'}{$instance}++; + + my $type = 'c:' . + $config_tree->getNodeParam( $ctoken, 'collector-type' ); + + my $period = + $config_tree->getNodeParam( $ctoken, 'collector-period' ); + $period = int( $period ); # make sure we're talking integers + + my $offset = $config_tree-> + getNodeParam( $ctoken, 'collector-timeoffset' ); + + $stats->{'leavesPerType'}{$type}++; + $stats->{'collectorSchedule'}{$instance}{$period}{ + $offset}{$type}++; + } + + if( defined( $config_tree->getNodeParam( $ctoken, 'monitor' ) ) ) + { + $stats->{'monitorLeaves'}++; + my $type = 'monitor'; + + my $period = + $config_tree->getNodeParam( $ctoken, 'monitor-period' ); + $period = int( $period ); # make sure we're talking integers + + my $offset = $config_tree-> + getNodeParam( $ctoken, 'monitor-timeoffset' ); + $offset = int($offset) % $period; + + $stats->{'leavesPerType'}{$type}++; + $stats->{'monitorSchedule'}{$period}{$offset}{$type}++; + } + } + } +} + + +# caluclate and print the schedule +sub reportTimeline +{ + my $schedule = shift; + + # calculate the common period length (least common multiple) + my $lcm = 0; + foreach my $period ( keys %{$schedule} ) + { + my $a = $period; + my $b = $lcm; + my $c; + if( $b == 0 ) + { + $lcm = $a; + } + else + { + if( $a < $b ) + { + my $tmp = $b; + $b = $a; + $a = $tmp; + } + while( $b != 0 ) + { + $c = $a % $b; + $a = $b; + $b = $c; + } + $lcm = $lcm * $period / $a; + } + } + + printf("Least common period: %d seconds\n", $lcm); + + # populate the common period + my %cp; + my $chunks = 0; + foreach my $period ( keys %{$schedule} ) + { + foreach my $offset ( keys %{$schedule->{$period}} ) + { + $chunks++; + foreach my $type ( keys %{$schedule->{$period}{$offset}} ) + { + for( my $i = 0; $i < ($lcm / $period); $i++ ) + { + $cp{$i * $period + $offset}{'col'}{$type} += + $schedule->{$period}{$offset}{$type}; + } + } + } + } + printf("Number of chunks: %d \n\n", $chunks ); + + # calculate interval lengths + + my $previous; + my $first; + foreach my $time ( sort { $a <=> $b } keys %cp ) + { + if( not defined($first) ) + { + $first = $time; + } + else + { + $cp{$previous}{'endtime'} = $time; + } + $previous = $time; + } + $cp{$previous}{'endtime'} = $lcm + $first; + + # print results + + thinLine(); + printf("%-10s%-10s%-20s%-10s\n", + 'Offset', 'Interval', 'Type', 'Data'); + printf("%-10s%-10s%-20s%-10s\n", + '(sec)', '(sec)', '', 'sources'); + thinLine(); + + foreach my $time ( sort { $a <=> $b } keys %cp ) + { + foreach my $type ( keys %{$cp{$time}{'col'}} ) + { + printf("%-10d%-10d%-20s%-10d\n", + $time, + $cp{$time}{'endtime'} - $time, + $type, + $cp{$time}{'col'}{$type} ); + } + } + thinLine(); + printf("\n"); +} + + +sub thickLine +{ + foreach my $i ( 1..75 ) + { + print '='; + } + print "\n"; +} + +sub thinLine +{ + foreach my $i ( 1..70 ) + { + print '-'; + } + print "\n"; +} + + + + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/snmpfailures.in b/torrus/bin/snmpfailures.in new file mode 100644 index 000000000..f46cc2d4c --- /dev/null +++ b/torrus/bin/snmpfailures.in @@ -0,0 +1,98 @@ +#!@PERL@ -w +# Copyright (C) 2010 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: snmpfailures.in,v 1.1 2010-12-27 00:04:03 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +BEGIN { require '@torrus_config_pl@'; } + +use strict; +use Getopt::Long; +use JSON; + +use Torrus::SiteConfig; +use Torrus::DB; +use Torrus::Log; +use Torrus::SNMP_Failures; + +exit(1) if not Torrus::SiteConfig::verify(); + + +my $tree; +my $print_details; + +my $help_needed; + + +my $ok = GetOptions('tree=s' => \$tree, + 'details' => \$print_details, + 'help' => \$help_needed); + +if( not $ok or not $tree or + $help_needed or scalar(@ARGV) > 0 ) +{ + print STDERR "Usage: $0 --tree=NAME [options...]\n", + "Options:\n", + " --tree=NAME tree name\n", + " --details print failure details\n", + " --help this help message\n"; + exit 1; +} + + +if( not Torrus::SiteConfig::treeExists( $tree ) ) +{ + Error('Tree ' . $tree . ' does not exist'); + exit 1; +} + + +my $out = {}; + +&Torrus::DB::setSafeSignalHandlers(); + +my $nInstances = Torrus::SiteConfig::collectorInstances( $tree ); +for( my $instance = 0; $instance < $nInstances; $instance++ ) +{ + my $db_failures = new Torrus::SNMP_Failures( -Tree => $tree, + -Instance => $instance ); + + if( not defined( $db_failures ) ) + { + exit(1); + } + + + $db_failures->read( $out, -details => $print_details ); + undef $db_failures; +} + + +my $json = new JSON; +$json->canonical(); +$json->pretty(); +print $json->encode($out); + + +exit(0); + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/srvderive.in b/torrus/bin/srvderive.in new file mode 100644 index 000000000..17749170c --- /dev/null +++ b/torrus/bin/srvderive.in @@ -0,0 +1,371 @@ +#!@PERL@ +# Copyright (C) 2008 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: srvderive.in,v 1.1 2010-12-27 00:04:02 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +# Combine SUM or MAX from several service IDs and create a new one + +BEGIN { require '@torrus_config_pl@'; } + +use strict; +use POSIX qw(floor); +use Getopt::Long; +use Date::Parse; +use Date::Format; +use Math::BigFloat; + +use Torrus::Log; +use Torrus::ServiceID; +use Torrus::SQL::SrvExport; + +my $startdate; +my $enddate; +my $onemonth; + +my $function; +my @input; +my $output; + +my $step = 300; + +my $debug; +my $verbose; +my $help_needed; + +my %known_functions = ('MAX' => \&function_max, 'SUM' => \&function_sum); + + +my $ok = GetOptions( + 'start=s' => \$startdate, + 'end=s' => \$enddate, + 'month' => \$onemonth, + 'func=s' => \$function, + 'in=s' => \@input, + 'out=s' => \$output, + 'step=i' => \$step, + 'verbose' => \$verbose, + 'debug' => \$debug, + 'help' => \$help_needed, + ); + +if( $help_needed or not $ok or (not $startdate) or + (defined($enddate) + defined($onemonth) != 1) or + not $function or + (scalar(@input) < 2 and scalar( @ARGV ) < 2) or + not $output ) +{ + print STDERR "Usage: $0 TIMESPAN OUTPUT FUNCTION SOURCES...\n\n", + "TIMESPAN:\n", + " --start=YYYY-MM-DD [mandatory] Start date\n", + " --month [optional] Calendar month timespan\n", + " --end=YYYY-MM-DD [optional] Next day after the timespan end\n", + " Either --month or --end option must be defined\n\n", + "OUTPUT:\n", + " --out=SERVICEID [mandatory] Output Service ID\n\n", + "FUNCTION:\n", + " --func=MAX|SUM [mandatory] Aggregation function\n\n", + "SOURCES:\n", + " Either --in=SERVICEID, or Service ID names as command line ", + "arguments.\n", + " Minimum 2 sources required\n\n", + "Options:\n", + " --step=N [300] service data interval\n", + " --verbose print extra information\n", + " --debug print debugging information\n", + " --help print usage information\n", + "\n"; + + exit 1; +} + +push(@input, @ARGV); + +if( not defined($known_functions{$function}) ) +{ + printf STDERR ("Unknown function: %s. Must be onne of: %s\n", + $function, join(', ', sort keys %known_functions)); + exit 1; +} + + + +if( $debug ) +{ + Torrus::Log::setLevel('debug'); +} +elsif( $verbose ) +{ + Torrus::Log::setLevel('verbose'); +} + + +my $starttime = str2time( $startdate ); +if( not defined($starttime) ) +{ + Error('Cannot parse start date: ' . $startdate); + exit 1; +} + +# Canonize the date +$startdate = time2str('%Y-%m-%d', $starttime); + +my $endtime; + +if( defined($enddate) ) +{ + $endtime = str2time( $startdate ); + if( not defined($endtime) ) + { + Error('Cannot parse end date: ' . $enddate); + exit 1; + } + + if( $endtime < $starttime ) + { + Error('End date is earlier than start date'); + exit 1; + } +} +else +{ + # Calculate +1 calendar month + + my ($ss,$mm,$hh,$day,$month,$year,$zone) = + strptime( $startdate ); + $year += 1900; + $month++; + $day++; + + my $endyear = $year; + my $endmonth = $month + 1; + + if( $endmonth > 12 ) + { + $endmonth = 1; + $endyear++; + } + + $endtime = str2time( sprintf('%.4d-%.2d-%.2d', + $endyear, $endmonth, $day) ); + if( not defined($endtime) ) + { + # oops, it was past the end of the month + $day++; + $endmonth++; + if( $endmonth > 12 ) + { + $endmonth = 1; + $endyear++; + } + + $endtime = str2time( sprintf('%.4d-%.2d-%.2d', + $endyear, $endmonth, $day) ); + + if( not defined($endtime) ) + { + Error('Cannot determine the end date'); + exit 1; + } + } +} + +# Canonize the date +$enddate = time2str('%Y-%m-%d', $endtime); + + +Verbose('Start time: ', scalar(localtime($starttime))); +Verbose('End time: ', scalar(localtime($endtime))); + +my $srvExp = Torrus::SQL::SrvExport->new(); +if( not defined( $srvExp ) ) +{ + Error('Cannot connect to the SQL database'); + exit 1; +} + +my $srvIDs = $srvExp->getServiceIDs(); + +foreach my $serviceid ( @input ) +{ + if( not grep {$serviceid eq $_} @{$srvIDs} ) + { + Error('Input service ID not found in the database: ' . $serviceid); + exit 1; + } +} + +&Torrus::DB::setSafeSignalHandlers(); + +# Check if the output ServiceID exists in the local database +# The database contains only IDs generated from datasource trees. + +my $srvIDParams = new Torrus::ServiceID(); +if( $srvIDParams->idExists( $output ) ) +{ + Error('Output service ID was previously created from Torrus ' . + 'datasource tree. Cannot override it: ' . $output); + exit 1; +} +&Torrus::DB::cleanupEnvironment(); +&Torrus::DB::setUnsafeSignalHandlers(); + + +my %in_data; + +foreach my $serviceid ( @input ) +{ + $in_data{$serviceid} = + $srvExp->getIntervalData( $startdate, $enddate, $serviceid ); + + Verbose(sprintf('Loaded %d rows of data for %s', + scalar( @{$in_data{$serviceid}} ), + $serviceid)); +} + +my $n_points = floor( ($endtime - $starttime) / $step ); + +my %aligned_data; + +foreach my $serviceid ( @input ) +{ + my @aligned = (); + $#aligned = $n_points; + + # Fill in the aligned array. For each interval by modulo(step), + # we take the sum of values that get into that interval + + foreach my $row ( @{$in_data{$serviceid}} ) + { + my $rowtime = str2time( $row->{'srv_date'} . 'T' . + $row->{'srv_time'} ); + + my $pos = floor( ($rowtime - $starttime) / $step ); + my $value = Math::BigFloat->new( $row->{'value'} ); + if( $value->is_nan() ) + { + $value->bzero(); + } + + if( not defined($aligned[$pos])) + { + $aligned[$pos] = $value; + } + else + { + $aligned[$pos]->badd($value); + } + } + + $aligned_data{$serviceid} = \@aligned; +} + +Verbose(sprintf('Aligned data into %d intervals', $n_points)); + +# Store the derived data +my $dbh = Torrus::SQL::SrvExport->dbh(); +if( not defined( $dbh ) ) +{ + Error('Lost SQL connection'); + exit 1; +} + +my $sth = $dbh->prepare( Torrus::SQL::SrvExport->sqlInsertStatement() ); +if( not defined( $sth ) ) +{ + Error('Error preparing the SQL statement: ' . $dbh->errstr); +} + + + +for( my $pos = 0; $pos < $n_points; $pos++ ) +{ + my @args; + foreach my $serviceid ( @input ) + { + my $val = $aligned_data{$serviceid}->[$pos]; + if( defined( $val ) ) + { + push( @args, $val ); + } + } + + if( scalar( @args ) > 0 ) + { + my $value = &{$known_functions{$function}}(@args); + + my $timestamp = $starttime + $pos * $step; + my $datestr = time2str('%Y-%m-%d', $timestamp); + my $timestr = time2str('%H:%M:%S', $timestamp); + + if( isDebug() ) + { + Debug('Updating SQL database: ' . + join(', ', $datestr, $timestr, + $output, $value, $step )); + } + + if( not $sth->execute( $datestr, $timestr, + $output, $value, $step ) ) + { + Error('Error executing SQL: ' . $dbh->errstr); + exit 1; + } + } +} + +Verbose('Database update finished'); + +exit($ok ? 0:1); + + +sub function_max +{ + my $value = Math::BigFloat->new(); + $value->binf('-'); + + foreach my $a ( @_ ) + { + if( $value->bcmp($a) < 0 ) + { + $value = Math::BigFloat->new($a); + } + } + + return $value; +} + + +sub function_sum +{ + my $value = Math::BigFloat->new(0); + + foreach my $a ( @_ ) + { + $value->badd($a); + } + + return $value; +} + + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/torrus.fcgi.in b/torrus/bin/torrus.fcgi.in new file mode 100644 index 000000000..fc6ee41a2 --- /dev/null +++ b/torrus/bin/torrus.fcgi.in @@ -0,0 +1,50 @@ +#!@PERL@ -w +# Copyright (C) 2010 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: torrus.fcgi.in,v 1.1 2010-12-27 00:04:02 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + +# FastCGI handler +# Can be used as alternative to mod_perl in Apache +# Can also be used with lighttpd + + +BEGIN { require '@torrus_config_pl@'; } + +use strict; +use CGI::Fast; +use Torrus::Log; +use Torrus::CGI; + + +if( $Torrus::Renderer::globalDebug ) +{ + &Torrus::Log::setLevel('debug'); +} + + +while( my $q = new CGI::Fast ) +{ + Torrus::CGI->process($q); +} + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/torrus.in b/torrus/bin/torrus.in new file mode 100644 index 000000000..7c5118c2c --- /dev/null +++ b/torrus/bin/torrus.in @@ -0,0 +1,76 @@ +#!@SHELL@ +# Copyright (C) 2004 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: torrus.in,v 1.1 2010-12-27 00:04:00 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> +# + +# CLI wrapper for Torrus utilities + +cmd=$1 + +commands="acl=acledit acledit=acledit \ + bs=buildsearchdb buildsearchdb=buildsearchdb \ + cleanup=cleanup \ + clc=clearcache clearcache=clearcache \ + collector=collector \ + compile=compilexml compilexml=compilexml \ + configinfo=configinfo ci=configinfo \ + snapshot=configsnapshot configsnapshot=configsnapshot \ + dd=devdiscover discover=devdiscover devdiscover=devdiscover \ + fm=flushmonitors flushmonitors=flushmonitors \ + genddx=genddx \ + genlist=genlist \ + genreport=genreport report=genreport \ + install_plugin=install_plugin \ + monitor=monitor \ + nodeid=nodeid ni=nodeid \ + rrddir=rrddir2xml rrddir2xml=rrddir2xml \ + schedulerinfo=schedulerinfo si=schedulerinfo \ + snmpfailures=snmpfailures failures=snmpfailures \ + srvderive=srvderive derive=srvderive \ + ttproclist=ttproclist" + +for f in `ls -1 @plugwrapperdir@`; do + . @plugwrapperdir@/${f} +done + +for pair in ${commands}; do + eval execcmd_${pair} +done + +eval expanded_cmd='${execcmd_'${cmd}'}' + + +if test ${expanded_cmd:-no} = no; then + echo "Usage: $0 cmd [options...]" 1>&2 + echo " cmd is one of:" 1>&2 + for pair in ${commands}; do + eval `echo ${pair} | sed -e 's/=.*//' -e 's/^/a=/'` + echo " "${a} + done +else + shift + @pkgbindir@/${expanded_cmd} "$@" +fi + + +# Local Variables: +# mode: shell-script +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: diff --git a/torrus/bin/ttproclist.in b/torrus/bin/ttproclist.in new file mode 100644 index 000000000..614cdd618 --- /dev/null +++ b/torrus/bin/ttproclist.in @@ -0,0 +1,135 @@ +#!@PERL@ +# Copyright (C) 2005 Stanislav Sinyagin +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +# $Id: ttproclist.in,v 1.1 2010-12-27 00:04:03 ivan Exp $ +# Stanislav Sinyagin <ssinyagin@yahoo.com> + + +use strict; +use Template; +use Getopt::Long; + +my $template; +my $outfile; +my $nodelist; +my $parameters; + + +my $creator = "Torrus version @VERSION@\n" . + "This file was generated by command:\n" . + $0 . " \\\n"; +foreach my $arg ( @ARGV ) +{ + if( $arg =~ /^--/ ) + { + $creator .= ' ' . $arg . ' '; + } + else + { + $creator .= "\'" . $arg . "\'\\\n"; + } +} +$creator .= "\nOn " . scalar(localtime(time)); + + +my $ok = GetOptions( 'tmpl=s' => \$template, + 'out=s' => \$outfile, + 'nodes=s' => \$nodelist, + 'param=s' => \$parameters ); + +if( not $ok or not $template or not $outfile or not $nodelist) +{ + print STDERR "Process a template with a nodelist\n\n"; + + print STDERR "Usage: $0 options...\n", + "Mandatory options:\n", + " --tmpl=filename template file name\n", + " --out=filename output file\n", + " --nodes=filename file with nodes\n", + "Options:\n", + " --param=NAME:VALUE,NAME:VALUE... parameters passed to template\n"; + exit 1; +} + +my @rawnodes; + +if( not open( NODES, $nodelist ) ) +{ + print STDERR "Cannot open $nodelist: $!\n"; + exit 1; +} +while(<NODES>) +{ + s/^\s+//; + s/\s+$//; + push( @rawnodes, split( /\s+/ ) ); +} +close( NODES ); + +my %nodes; +foreach my $node ( @rawnodes ) +{ + my $symname = $node; + if( $node =~ /([^:]+):(.+)/ ) + { + $node = $1; + $symname = $2; + } + + $nodes{$node} = $symname; +} + +my %params; +if( defined( $parameters ) ) +{ + foreach my $pair ( split( '\s*,\s*', $parameters ) ) + { + my ($name, $val) = split( '\s*:\s*', $pair ); + $params{$name} = $val; + } +} + +my $tt = new Template( INCLUDE_PATH => '@tmpluserdir@', + ABSOLUTE => 1, + RELATIVE => 1, + TRIM => 1 ); + +my $vars = +{ + 'nodes' => \%nodes, + 'param' => \%params, + 'nodesfile' => $nodelist, + 'creator' => $creator, + 'lc' => sub{ return lc $_[0] }, + 'uc' => sub{ return uc $_[0] } +}; + +my $result = $tt->process($template, $vars, $outfile); + +if( not $result ) +{ + print STDERR "Error while processing template: ".$tt->error()."\n"; +} + +exit( $result ? 0:1 ); + + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 4 +# End: |