diff options
| -rw-r--r-- | .gitignore | 26 | ||||
| -rw-r--r-- | AUTHORS | 0 | ||||
| -rw-r--r-- | COPYING | 340 | ||||
| -rw-r--r-- | ChangeLog | 0 | ||||
| -rw-r--r-- | Makefile.am | 78 | ||||
| -rw-r--r-- | NEWS | 0 | ||||
| -rw-r--r-- | README | 28 | ||||
| -rwxr-xr-x | autogen.sh | 30 | ||||
| -rw-r--r-- | build-aux/Makefile.subs | 34 | ||||
| -rwxr-xr-x | build-aux/gitlog-to-changelog | 194 | ||||
| -rwxr-xr-x | build-aux/pkg-version | 52 | ||||
| -rw-r--r-- | configure.ac | 103 | ||||
| -rw-r--r-- | gluster-nagios-addons.spec.in | 79 | ||||
| -rw-r--r-- | m4/ax_python_module.m4 | 49 | ||||
| -rw-r--r-- | plugins/Makefile.am | 2 | ||||
| -rwxr-xr-x | rfc.sh | 114 | ||||
| -rw-r--r-- | tests/Makefile.am | 50 | ||||
| -rw-r--r-- | tests/README | 11 | ||||
| -rw-r--r-- | tests/run_tests.sh.in | 10 | ||||
| -rw-r--r-- | tests/run_tests_local.sh.in | 6 | ||||
| -rw-r--r-- | tests/testValidation.py | 141 | ||||
| -rw-r--r-- | tests/testrunner.py | 308 | 
22 files changed, 1655 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9b712a9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +*.iml +*.o +*.pyc +*.swp +*.tmp +*~ +.deps +.idea +.project +.pydevproject +INSTALL +Makefile +Makefile.in +aclocal.m4 +autom4te.cache +build-aux/depcomp +build-aux/install-sh +build-aux/missing +build-aux/py-compile +config.log +config.status +configure +tests/run_tests.sh +tests/run_tests_local.sh +gluster-nagios-addons-*.tar.gz +gluster-nagios-addons.spec @@ -0,0 +1,340 @@ +		    GNU GENERAL PUBLIC LICENSE +		       Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. +     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +			    Preamble + +  The licenses for most software are designed to take away your +freedom to share and change it.  By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users.  This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it.  (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.)  You can apply it to +your programs, too. + +  When we speak of free software, we are referring to freedom, not +price.  Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + +  To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + +  For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have.  You must make sure that they, too, receive or can get the +source code.  And you must show them these terms so they know their +rights. + +  We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +  Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software.  If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + +  Finally, any free program is threatened constantly by software +patents.  We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary.  To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + +  The precise terms and conditions for copying, distribution and +modification follow. + +		    GNU GENERAL PUBLIC LICENSE +   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +  0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License.  The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language.  (Hereinafter, translation is included without limitation in +the term "modification".)  Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope.  The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + +  1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + +  2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + +    a) You must cause the modified files to carry prominent notices +    stating that you changed the files and the date of any change. + +    b) You must cause any work that you distribute or publish, that in +    whole or in part contains or is derived from the Program or any +    part thereof, to be licensed as a whole at no charge to all third +    parties under the terms of this License. + +    c) If the modified program normally reads commands interactively +    when run, you must cause it, when started running for such +    interactive use in the most ordinary way, to print or display an +    announcement including an appropriate copyright notice and a +    notice that there is no warranty (or else, saying that you provide +    a warranty) and that users may redistribute the program under +    these conditions, and telling the user how to view a copy of this +    License.  (Exception: if the Program itself is interactive but +    does not normally print such an announcement, your work based on +    the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole.  If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works.  But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +  3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + +    a) Accompany it with the complete corresponding machine-readable +    source code, which must be distributed under the terms of Sections +    1 and 2 above on a medium customarily used for software interchange; or, + +    b) Accompany it with a written offer, valid for at least three +    years, to give any third party, for a charge no more than your +    cost of physically performing source distribution, a complete +    machine-readable copy of the corresponding source code, to be +    distributed under the terms of Sections 1 and 2 above on a medium +    customarily used for software interchange; or, + +    c) Accompany it with the information you received as to the offer +    to distribute corresponding source code.  (This alternative is +    allowed only for noncommercial distribution and only if you +    received the program in object code or executable form with such +    an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it.  For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable.  However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + +  4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License.  Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + +  5. You are not required to accept this License, since you have not +signed it.  However, nothing else grants you permission to modify or +distribute the Program or its derivative works.  These actions are +prohibited by law if you do not accept this License.  Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +  6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions.  You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + +  7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License.  If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all.  For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices.  Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + +  8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded.  In such case, this License incorporates +the limitation as if written in the body of this License. + +  9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time.  Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number.  If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation.  If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + +  10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission.  For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this.  Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + +			    NO WARRANTY + +  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + +  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +		     END OF TERMS AND CONDITIONS + +	    How to Apply These Terms to Your New Programs + +  If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +  To do so, attach the following notices to the program.  It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + +    <one line to give the program's name and a brief idea of what it does.> +    Copyright (C) <year>  <name of author> + +    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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + +    Gnomovision version 69, Copyright (C) year  name of author +    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +    This is free software, and you are welcome to redistribute it +    under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License.  Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary.  Here is a sample; alter the names: + +  Yoyodyne, Inc., hereby disclaims all copyright interest in the program +  `Gnomovision' (which makes passes at compilers) written by James Hacker. + +  <signature of Ty Coon>, 1 April 1989 +  Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs.  If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library.  If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/ChangeLog diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..5ffc3af --- /dev/null +++ b/Makefile.am @@ -0,0 +1,78 @@ +# +# Copyright 2014 Red Hat, Inc. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +# +# Refer to the README and COPYING files for full details of the license +# + +# keep sorted +SUBDIRS = \ +	plugins \ +	$(NULL) + +# The tests should be always last as they need the rest of the source to be +# prepared before running. +SUBDIRS += tests + +EXTRA_DIST = \ +	build-aux/pkg-version \ +	gluster-nagios-addons.spec \ +	gluster-nagios-addons.spec.in + +CLEANFILES = \ +	gluster-nagios-addons.spec \ +	$(DIST_ARCHIVES) \ +	$(NULL) + +check-local: +	find . -path './.git' -prune -type f -o \ +		-name '*.py' -o -name '*.py.in'  | xargs $(PYFLAKES) | \ +		while read LINE; do echo "$$LINE"; false; done +	$(PEP8) --version +	$(PEP8) --filename '*.py,*.py.in' $(top_srcdir) +	@if test -f .gitignore; then \ +	  for i in `git ls-files \*.in`; do \ +	    if ! grep -q -x $${i%%.in} .gitignore; then \ +	      echo "Missing $${i%%.in} in .gitignore"; exit 1; fi; \ +	  done; \ +	fi; + +all-local: \ +	gluster-nagios-addons.spec + +.PHONY: srpm rpm + +srpm: dist +	rpmbuild -ts $(if $(BUILDID),--define="extra_release .$(BUILDID)") $(DIST_ARCHIVES) + +rpm: dist +	rpmbuild -ta $(if $(BUILDID),--define="extra_release .$(BUILDID)") \ +				$(WITH_HOOKS) $(DIST_ARCHIVES) + +dist-hook: gen-VERSION gen-ChangeLog +.PHONY: gen-VERSION gen-ChangeLog + +gen-ChangeLog: +	if test -d .git; then \ +	  $(top_srcdir)/build-aux/gitlog-to-changelog \ +	    > $(distdir)/ChangeLog; \ +	fi + +gen-VERSION: +	if test -d .git; then \ +	  $(top_srcdir)/build-aux/pkg-version --full \ +	    > $(distdir)/VERSION; \ +	fi @@ -0,0 +1,28 @@ + +Gluster Nagios Add-ons: +======================= +Nagios plugin, scripts, configuration files etc for gluster nodes. + + +Installation +============ +The Gluster Nagios Add-ons can be used by following the standard +autotools installation process, documented in the INSTALL file. As a +quick start you can do + +   ./configure --prefix=/usr --sysconfdir=/etc \ +        --localstatedir=/var --libdir=/usr/lib +   make +   sudo make install + + +Packaging +========= +The 'gluster-nagios-addons.spec' file demonstrates how to distribute +this as an RPM package. + + +Getting Help +============ + +-- End of readme diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..4979329 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +autoreconf -if + +if test "x$1" = "x--system"; then +    shift +    prefix=/usr +    libdir=$prefix/lib +    sysconfdir=/etc +    localstatedir=/var +    if [ -d /usr/lib64 ]; then +      libdir=$prefix/lib64 +    fi +    EXTRA_ARGS="--prefix=$prefix --sysconfdir=$sysconfdir --localstatedir=$localstatedir --libdir=$libdir" +    echo "Running ./configure with $EXTRA_ARGS $@" +else +    if test -z "$*" && test ! -f "$THEDIR/config.status"; then +        echo "I am going to run ./configure with no arguments - if you wish " +        echo "to pass any to it, please specify them on the $0 command line." +    fi +fi + +if test -z "$*" && test -f config.status; then +    ./config.status --recheck +else +    ./configure $EXTRA_ARGS "$@" +fi && { +    echo +    echo "Now type 'make' to compile." +} diff --git a/build-aux/Makefile.subs b/build-aux/Makefile.subs new file mode 100644 index 0000000..ff395f7 --- /dev/null +++ b/build-aux/Makefile.subs @@ -0,0 +1,34 @@ +# +# Copyright 2014 Red Hat, Inc. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +# +# Refer to the README and COPYING files for full details of the license +# + +SUFFIXES: .in + +# Reference: +# http://www.gnu.org/software/automake/manual/html_node/Scripts.html +PATHSUBST = sed \ +	-e "s,[@]NAGIOSPLUGINSDIR[@],$(nagiospluginsdir),g" \ +	-e "s,[@]GLUSTERHOSTPLUGINSDIR[@],$(glusterhostpluginsdir),g" \ +	-e "s,[@]GLUSTERADDONSTESTSDIR[@],$(glusteraddonstestsdir),g" \ +	-e "s,[@]GLUSTERADDONSPYLIBDIR[@],$(glusteraddonspylibdir),g" + +CONFIGSUBST = $(top_builddir)/config.status --file=- + +%: %.in +	@echo "  SED $@"; $(PATHSUBST) $< |$(CONFIGSUBST) >$@ diff --git a/build-aux/gitlog-to-changelog b/build-aux/gitlog-to-changelog new file mode 100755 index 0000000..b0db305 --- /dev/null +++ b/build-aux/gitlog-to-changelog @@ -0,0 +1,194 @@ +eval '(exit $?0)' && eval 'exec perl -wS "$0" ${1+"$@"}' +  & eval 'exec perl -wS "$0" $argv:q' +    if 0; +# Convert git log output to ChangeLog format. + +my $VERSION = '2009-10-30 13:46'; # UTC +# The definition above must lie within the first 8 lines in order +# for the Emacs time-stamp write hook (at end) to update it. +# If you change this file with Emacs, please let the write hook +# do its job.  Otherwise, update this string manually. + +# Copyright (C) 2008-2011 Free Software Foundation, Inc. + +# 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 3 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, see <http://www.gnu.org/licenses/>. + +# Written by Jim Meyering + +use strict; +use warnings; +use Getopt::Long; +use POSIX qw(strftime); + +(my $ME = $0) =~ s|.*/||; + +# use File::Coda; # http://meyering.net/code/Coda/ +END { +  defined fileno STDOUT or return; +  close STDOUT and return; +  warn "$ME: failed to close standard output: $!\n"; +  $? ||= 1; +} + +sub usage ($) +{ +  my ($exit_code) = @_; +  my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR); +  if ($exit_code != 0) +    { +      print $STREAM "Try `$ME --help' for more information.\n"; +    } +  else +    { +      print $STREAM <<EOF; +Usage: $ME [OPTIONS] [ARGS] + +Convert git log output to ChangeLog format.  If present, any ARGS +are passed to "git log".  To avoid ARGS being parsed as options to +$ME, they may be preceded by '--'. + +OPTIONS: + +   --since=DATE convert only the logs since DATE; +                  the default is to convert all log entries. +   --format=FMT set format string for commit subject and body; +                  see 'man git-log' for the list of format metacharacters; +                  the default is '%s%n%b%n' + +   --help       display this help and exit +   --version    output version information and exit + +EXAMPLE: + +  $ME --since=2008-01-01 > ChangeLog +  $ME -- -n 5 foo > last-5-commits-to-branch-foo + +EOF +    } +  exit $exit_code; +} + +# If the string $S is a well-behaved file name, simply return it. +# If it contains white space, quotes, etc., quote it, and return the new string. +sub shell_quote($) +{ +  my ($s) = @_; +  if ($s =~ m![^\w+/.,-]!) +    { +      # Convert each single quote to '\'' +      $s =~ s/\'/\'\\\'\'/g; +      # Then single quote the string. +      $s = "'$s'"; +    } +  return $s; +} + +sub quoted_cmd(@) +{ +  return join (' ', map {shell_quote $_} @_); +} + +{ +  my $since_date = '1970-01-01 UTC'; +  my $format_string = '%s%n%b%n'; +  GetOptions +    ( +     help => sub { usage 0 }, +     version => sub { print "$ME version $VERSION\n"; exit }, +     'since=s' => \$since_date, +     'format=s' => \$format_string, +    ) or usage 1; + +  my @cmd = (qw (git log --log-size), "--since=$since_date", +             '--pretty=format:%ct  %an  <%ae>%n%n'.$format_string, @ARGV); +  open PIPE, '-|', @cmd +    or die ("$ME: failed to run `". quoted_cmd (@cmd) ."': $!\n" +            . "(Is your Git too old?  Version 1.5.1 or later is required.)\n"); + +  my $prev_date_line = ''; +  while (1) +    { +      defined (my $in = <PIPE>) +        or last; +      $in =~ /^log size (\d+)$/ +        or die "$ME:$.: Invalid line (expected log size):\n$in"; +      my $log_nbytes = $1; + +      my $log; +      my $n_read = read PIPE, $log, $log_nbytes; +      $n_read == $log_nbytes +        or die "$ME:$.: unexpected EOF\n"; + +      my @line = split "\n", $log; +      my $author_line = shift @line; +      defined $author_line +        or die "$ME:$.: unexpected EOF\n"; +      $author_line =~ /^(\d+)  (.*>)$/ +        or die "$ME:$.: Invalid line " +          . "(expected date/author/email):\n$author_line\n"; + +      my $date_line = sprintf "%s  $2\n", strftime ("%F", localtime ($1)); +      # If this line would be the same as the previous date/name/email +      # line, then arrange not to print it. +      if ($date_line ne $prev_date_line) +        { +          $prev_date_line eq '' +            or print "\n"; +          print $date_line; +        } +      $prev_date_line = $date_line; + +      # Omit "Signed-off-by..." lines. +      @line = grep !/^Signed-off-by: .*>$/, @line; + +      # Omit gerrit lines. +      @line = grep !/^(Change-Id|Reviewed-(on|by)|Tested-by): .*$/, @line; + +      # If there were any lines +      if (@line == 0) +        { +          warn "$ME: warning: empty commit message:\n  $date_line\n"; +        } +      else +        { +          # Remove leading and trailing blank lines. +          while ($line[0] =~ /^\s*$/) { shift @line; } +          while ($line[$#line] =~ /^\s*$/) { pop @line; } + +          # Prefix each non-empty line with a TAB. +          @line = map { length $_ ? "\t$_" : '' } @line; + +          print "\n", join ("\n", @line), "\n"; +        } + +      defined ($in = <PIPE>) +        or last; +      $in ne "\n" +        and die "$ME:$.: unexpected line:\n$in"; +    } + +  close PIPE +    or die "$ME: error closing pipe from " . quoted_cmd (@cmd) . "\n"; +  # FIXME-someday: include $PROCESS_STATUS in the diagnostic +} + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "my $VERSION = '" +# time-stamp-format: "%:y-%02m-%02d %02H:%02M" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "'; # UTC" +# End: diff --git a/build-aux/pkg-version b/build-aux/pkg-version new file mode 100755 index 0000000..2be2a97 --- /dev/null +++ b/build-aux/pkg-version @@ -0,0 +1,52 @@ +#!/bin/sh + +# To override version/release from git, +# create VERSION file containing text with version/release +# eg. v3.4.0-1 +PKG_VERSION=`cat VERSION 2> /dev/null || git describe --tags --match "v[0-9]*"` + +function get_version () +{ +    # tags and output versions: +    #   - v3.4.0   => 3.4.0 (upstream clean) +    #   - v3.4.0-1 => 3.4.0 (downstream clean) +    #   - v3.4.0-2-g34e62f   => 3.4.0 (upstream dirty) +    #   - v3.4.0-1-2-g34e62f => 3.4.0 (downstream dirty) +    AWK_VERSION=' +    BEGIN { FS="-" } +    /^v[0-9]/ { +      sub(/^v/,"") ; print $1 +    }' + +    echo $PKG_VERSION | awk "$AWK_VERSION" | tr -cd '[:alnum:].' +} + +function get_release () +{ +    # tags and output releases: +    #   - v3.4.0   => 0 (upstream clean) +    #   - v3.4.0-1 => 1 (downstream clean) +    #   - v3.4.0-2-g34e62f1   => 2.git34e62f1 (upstream dirty) +    #   - v3.4.0-1-2-g34e62f1 => 1.2.git34e62f1 (downstream dirty) +    AWK_RELEASE=' +    BEGIN { FS="-"; OFS="." } +    /^v[0-9]/ { +      if (NF == 1) print 0 +      else if (NF == 2) print $2 +      else if (NF == 3) print $2, "git" substr($3, 2) +      else if (NF == 4) print $2, $3, "git" substr($4, 2) +    }' + +    echo $PKG_VERSION | awk "$AWK_RELEASE" | tr -cd '[:alnum:].' +} + +if test "x$1" = "x--full"; then +    echo -n "v$(get_version)-$(get_release)" +elif test "x$1" = "x--version"; then +    get_version +elif test "x$1" = "x--release"; then +    get_release +else +    echo "usage: $0 [--full|--version|--release]" +    exit 1 +fi diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..6b6f1d2 --- /dev/null +++ b/configure.ac @@ -0,0 +1,103 @@ +# +# Copyright 2014 Red Hat, Inc. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +# +# Refer to the README and COPYING files for full details of the license +# + +# Autoconf initialization +AC_INIT([gluster-nagios-addons], +        [m4_esyscmd([build-aux/pkg-version --version])], +        [rhs-bugs@redhat.com]) +AC_CONFIG_AUX_DIR([build-aux]) + +m4_include([m4/ax_python_module.m4]) + +# Package release +AC_SUBST([PACKAGE_RELEASE], +         [m4_esyscmd([build-aux/pkg-version --release])]) + +# Testing for version and release +AS_IF([test "x$PACKAGE_VERSION" = x], +      AC_MSG_ERROR([package version not defined])) +AS_IF([test "x$PACKAGE_RELEASE" = x], +      AC_MSG_ERROR([package release not defined])) + +# Automake initialization +AM_INIT_AUTOMAKE([-Wno-portability]) + +# Checking for build tools +AC_PROG_CC +AC_PROG_LN_S +AM_PATH_PYTHON([2.6]) + +# Users and groups +AC_SUBST([NAGIOSUSER], [nagios]) +AC_SUBST([NAGIOSGROUP], [nagios]) + +# default paths +AC_SUBST([nagiospluginsdir], ['${libdir}/nagios/plugins']) +AC_SUBST([glusternagiospluginsdir], ['${nagiospluginsdir}/gluster']) +AC_SUBST([glusternagioscommonpylibdir], ['${pyexecdir}/glusternagios']) +AC_SUBST([glusternagiosaddonstestsdir], ['${datarootdir}/${PACKAGE_NAME}/tests']) + +# Checking for pyflakes +AC_PATH_PROG([PYFLAKES], [pyflakes]) +if test "x$PYFLAKES" = "x"; then +  AC_MSG_WARN([pyflakes not found]) +fi + +# Checking for pep8 +AC_PATH_PROG([PEP8], [pep8]) +if test "x$PEP8" = "x"; then +  AC_MSG_WARN([python-pep8 not found]) +fi + +# Checking for python-devel +AC_PATH_PROG([PYTHON_CONFIG], [python-config]) +if test "x$PYTHON_CONFIG" = "x"; then +  AC_MSG_ERROR([python-devel not found, please install it.]) +fi + +# Checking for nosetests +AC_PATH_PROG([NOSETESTS], [nosetests]) +if test "x$NOSETESTS" = "x"; then +  AC_MSG_ERROR([python-nose not found, please install it.]) +fi + +# Checking for python modules (sorted, please keep in order) +AX_PYTHON_MODULE([argparse], [fatal]) +AX_PYTHON_MODULE([ethtool], [fatal]) +AX_PYTHON_MODULE([glusternagios], [fatal]) +AX_PYTHON_MODULE([netaddr], [fatal]) +AX_PYTHON_MODULE([pthreading], [fatal]) +AX_PYTHON_MODULE([pyinotify], [fatal]) +AX_PYTHON_MODULE([selinux], [fatal]) + +# Keep sorted +AC_CONFIG_FILES([ +	Makefile +	gluster-nagios-addons.spec +	plugins/Makefile +	tests/Makefile +	tests/run_tests_local.sh +	tests/run_tests.sh +]) + +AC_OUTPUT([], [ +    chmod +x tests/run_tests.sh +    chmod +x tests/run_tests_local.sh +]) diff --git a/gluster-nagios-addons.spec.in b/gluster-nagios-addons.spec.in new file mode 100644 index 0000000..3450ba2 --- /dev/null +++ b/gluster-nagios-addons.spec.in @@ -0,0 +1,79 @@ +%global _hardened_build 1 + +%global _for_fedora_koji_builds 0 + +%if ( 0%{?fedora} && 0%{?fedora} > 16 ) || ( 0%{?rhel} && 0%{?rhel} > 6 ) +%global           _with_systemd true +%endif + +# From https://fedoraproject.org/wiki/Packaging:Python#Macros +%if ( 0%{?rhel} && 0%{?rhel} <= 5 ) +%{!?python_sitelib: %global python_sitelib %(python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")} +%{!?python_sitearch: %global python_sitearch %(python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1))")} +%endif + +Summary: Gluster node management add-ons for Nagios +Name:             @PACKAGE_NAME@ +Version:          @PACKAGE_VERSION@ +Release:          @PACKAGE_RELEASE@%{?dist} +License:          GPLv2+ +Group:            Applications/System +URL:              http://www.redhat.com +Vendor:           Red Hat, Inc. +Source0:          %{name}-%{version}.tar.gz +BuildRoot:        %{_tmppath}/%{name}-%{version}-root +BuildRequires:    pyflakes +BuildRequires:    python-pep8 +BuildRequires:    python-nose +BuildRequires:    python-devel +Requires:         gluster-nagios-common +Requires:         python-argparse +Requires:         python-ethtool +Requires:         python-netaddr +Requires:         python-pthreading +Requires:         python-pyinotify +Requires:         python-selinux + +%description +Nagios plugin, scripts, configuration files etc for gluster nodes. + +%package tests +Summary:          Unit/functional tests of Gluster node management add-ons for Nagios +Group:            Development/Tools +Requires:         %{name} = %{version}-%{release} +Requires:         pyflakes +Requires:         python-pep8 +Requires:         python-nose +Requires:         python-devel + +%description tests +Unit/functional tests for Nagios plugin, scripts, configuration files etc for gluster nodes. + +%prep +%setup -q + +%build +%{configure} +make + +%check +make check + +%install +rm -rf %{buildroot} +make install DESTDIR=%{buildroot} + +%clean +rm -rf %{buildroot} + +%files +%defattr(-,root,root,-) +%{_libdir}/nagios/* + +%files tests +%defattr(-,root,root,-) +%{_datadir}/%{name}/tests/* + +%changelog +* Sat Mar 08 2014 Bala FA <barumuga@redhat.com> +- Initial build. diff --git a/m4/ax_python_module.m4 b/m4/ax_python_module.m4 new file mode 100644 index 0000000..bd70a06 --- /dev/null +++ b/m4/ax_python_module.m4 @@ -0,0 +1,49 @@ +# =========================================================================== +#     http://www.gnu.org/software/autoconf-archive/ax_python_module.html +# =========================================================================== +# +# SYNOPSIS +# +#   AX_PYTHON_MODULE(modname[, fatal]) +# +# DESCRIPTION +# +#   Checks for Python module. +# +#   If fatal is non-empty then absence of a module will trigger an error. +# +# LICENSE +# +#   Copyright (c) 2008 Andrew Collier <colliera@ukzn.ac.za> +# +#   Copying and distribution of this file, with or without modification, are +#   permitted in any medium without royalty provided the copyright notice +#   and this notice are preserved. This file is offered as-is, without any +#   warranty. + +#serial 5 + +AU_ALIAS([AC_PYTHON_MODULE], [AX_PYTHON_MODULE]) +AC_DEFUN([AX_PYTHON_MODULE],[ +    if test -z $PYTHON; +    then +        PYTHON="python" +    fi +    PYTHON_NAME=`basename $PYTHON` +    AC_MSG_CHECKING($PYTHON_NAME module: $1) +	$PYTHON -c "import $1" 2>/dev/null +	if test $? -eq 0; +	then +		AC_MSG_RESULT(yes) +		eval AS_TR_CPP(HAVE_PYMOD_$1)=yes +	else +		AC_MSG_RESULT(no) +		eval AS_TR_CPP(HAVE_PYMOD_$1)=no +		# +		if test -n "$2" +		then +			AC_MSG_ERROR(failed to find required module $1) +			exit 1 +		fi +	fi +]) diff --git a/plugins/Makefile.am b/plugins/Makefile.am new file mode 100644 index 0000000..c12520c --- /dev/null +++ b/plugins/Makefile.am @@ -0,0 +1,2 @@ +dist_glusternagiosplugins_PYTHON = \ +	$(NULL) @@ -0,0 +1,114 @@ +#!/bin/sh -e + + +branch="master"; + + +set_hooks_commit_msg() +{ +    f=".git/hooks/commit-msg"; +    u="https://10.70.35.186:8443/tools/hooks/commit-msg"; + +    if [ -x "$f" ]; then +        return; +    fi + +    curl -k -o $f $u || wget --no-check-certificate -O $f $u; + +    chmod +x .git/hooks/commit-msg; + +    # Let the 'Change-Id: ' header get assigned on first run of rfc.sh +    GIT_EDITOR=true git commit --amend; +} + + +is_num() +{ +    local num; + +    num="$1"; + +    [ -z "$(echo $num | sed -e 's/[0-9]//g')" ] +} + + +rebase_changes() +{ +    git fetch origin; + +    GIT_EDITOR=$0 git rebase -i origin/$branch; +} + + +editor_mode() +{ +    if [ $(basename "$1") = "git-rebase-todo" ]; then +        sed 's/^pick /reword /g' "$1" > $1.new && mv $1.new $1; +        return; +    fi + +    if [ $(basename "$1") = "COMMIT_EDITMSG" ]; then +        if grep -qi '^BUG: ' $1; then +            return; +        fi +        while true; do +            echo Commit: "\"$(head -n 1 $1)\"" +            echo -n "Enter Bug ID: " +            read bug +            if [ -z "$bug" ]; then +                return; +            fi +            if ! is_num "$bug"; then +                echo "Invalid Bug ID ($bug)!!!"; +                continue; +            fi + +            sed "/^Change-Id:/{p; s/^.*$/BUG: $bug/;}" $1 > $1.new && \ +                mv $1.new $1; +            return; +        done +    fi + +    cat <<EOF +$0 - editor_mode called on unrecognized file $1 with content: +$(cat $1) +EOF +    return 1; +} + + +assert_diverge() +{ +    git diff origin/$branch..HEAD | grep -q .; +} + + +main() +{ +    set_hooks_commit_msg; + +    if [ -e "$1" ]; then +        editor_mode "$@"; +        return; +    fi + +    rebase_changes; + +    assert_diverge; + +    bug=$(git show --format='%b' | grep -i '^BUG: ' | awk '{print $2}'); + +    if [ "$DRY_RUN" = 1 ]; then +        drier='echo -e Please use the following command to send your commits to review:\n\n' +    else +        drier= +    fi + +    if [ -z "$bug" ]; then +        $drier git push origin HEAD:refs/for/$branch/rfc; +    else +        $drier git push origin HEAD:refs/for/$branch/bug-$bug; +    fi +} + +main "$@" diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..65843f4 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,50 @@ +# +# Copyright 2014 Red Hat, Inc. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +# +# Refer to the README and COPYING files for full details of the license +# + +test_modules = \ +	$(NULL) + +dist_glusternagiosaddonstests_DATA = \ +	$(NULL) + +dist_glusternagiosaddonstests_PYTHON = \ +	$(test_modules) \ +	testrunner.py \ +	testValidation.py \ +	$(NULL) + +dist_glusternagiosaddonstests_SCRIPTS = \ +	run_tests.sh \ +	$(NULL) + +dist_noinst_DATA = \ +	run_tests_local.sh \ +	$(NULL) + +CLEANFILES = \ +	$(NULL) + +all-local: \ +	$(nodist_glusternagiosaddonstests_PYTHON) + +check-local: +	@echo '*** Running tests.  To skip this step place NOSE_EXCLUDE=.* ***' +	@echo '*** into your environment.  Do not submit untested code!    ***' +	$(top_srcdir)/tests/run_tests_local.sh $(test_modules) diff --git a/tests/README b/tests/README new file mode 100644 index 0000000..3681917 --- /dev/null +++ b/tests/README @@ -0,0 +1,11 @@ +This test suite is built on the Nose framework.  For more information see: + +    http://readthedocs.org/docs/nose/en/latest/ + +Running the test suite: +----------------------- + +Running these tests is easy. + +~$ python testrunner.py +~$ python testrunner.py *.py diff --git a/tests/run_tests.sh.in b/tests/run_tests.sh.in new file mode 100644 index 0000000..fe2a476 --- /dev/null +++ b/tests/run_tests.sh.in @@ -0,0 +1,10 @@ +#!/bin/sh +if [ -z "$PYTHON_EXE" ]; then +    PYTHON_EXE="@PYTHON@" +fi + +prefix="@prefix@" +exec_prefix="@exec_prefix@" +pyexecdir="@pyexecdir@" +libdir="@libdir@" +LC_ALL=C PYTHONPATH="@glusternagioscommonpylibdir@:@nagiospluginsdir@" "$PYTHON_EXE" @top_srcdir@/tests/testrunner.py $@ diff --git a/tests/run_tests_local.sh.in b/tests/run_tests_local.sh.in new file mode 100644 index 0000000..39fc36a --- /dev/null +++ b/tests/run_tests_local.sh.in @@ -0,0 +1,6 @@ +#!/bin/sh +if [ -z "$PYTHON_EXE" ]; then +    PYTHON_EXE="@PYTHON@" +fi + +PYTHONDONTWRITEBYTECODE=1 LC_ALL=C PYTHONPATH="@top_srcdir@:$PYTHONPATH" "$PYTHON_EXE" @top_srcdir@/tests/testrunner.py $@ diff --git a/tests/testValidation.py b/tests/testValidation.py new file mode 100644 index 0000000..b46c9f8 --- /dev/null +++ b/tests/testValidation.py @@ -0,0 +1,141 @@ +# +# Copyright 2014 Red Hat, Inc. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA +# +# Refer to the README and COPYING files for full details of the license +# + +## This framework is mostly copied from vdsm test framework + +import os +from nose.plugins.skip import SkipTest +from functools import wraps +from nose.plugins import Plugin +import subprocess + + +class SlowTestsPlugin(Plugin): +    """Skips tests that might be too slow to be run for quick iteration +    builds""" +    name = 'slowtests' +    enabled = False + +    def add_options(self, parser, env=os.environ): +        env_opt = 'NOSE_SKIP_SLOW_TESTS' +        if env is None: +            default = False +        else: +            default = env.get(env_opt) + +        parser.add_option('--without-slow-tests', +                          action='store_true', +                          default=default, +                          dest='disable_slow_tests', +                          help='Some tests might take a long time to run, ' + +                               'use this to skip slow tests automatically.' + +                               '  [%s]' % env_opt) + +    def configure(self, options, conf): +        Plugin.configure(self, options, conf) +        if options.disable_slow_tests: +            SlowTestsPlugin.enabled = True + + +class StressTestsPlugin(Plugin): +    """ +    Denotes a test which stresses the resources of the system under test. Such +    tests should probably not be run in parallel.  This plugin provides a +    mechanism for parallel testing applications to skip stress tests. +    """ +    name = 'nonparalleltests' +    enabled = False + +    def add_options(self, parser, env=os.environ): +        env_opt = 'NOSE_SKIP_STRESS_TESTS' +        if env is None: +            default = False +        else: +            default = env.get(env_opt) + +        parser.add_option('--without-stress-tests', +                          action='store_true', +                          default=default, +                          dest='disable_stress_tests', +                          help='Some tests stress the resources of the ' + +                               'system under test.  Use this option to skip' + +                               'these tests (eg. when doing parallel' + +                               'testing [%s]' % env_opt) + +    def configure(self, options, conf): +        Plugin.configure(self, options, conf) +        if options.disable_stress_tests: +            StressTestsPlugin.enabled = True + + +def ValidateRunningAsRoot(f): +    @wraps(f) +    def wrapper(*args, **kwargs): +        if os.geteuid() != 0: +            raise SkipTest("This test must be run as root") + +        return f(*args, **kwargs) + +    return wrapper + + +def slowtest(f): +    @wraps(f) +    def wrapper(*args, **kwargs): +        if SlowTestsPlugin.enabled: +            raise SkipTest("Slow tests have been disabled") + +        return f(*args, **kwargs) + +    return wrapper + + +def brokentest(msg="Test failed but it is known to be broken"): +    def wrap(f): +        @wraps(f) +        def wrapper(*args, **kwargs): +            try: +                return f(*args, **kwargs) +            except: +                raise SkipTest(msg) +        return wrapper + +    return wrap + + +def stresstest(f): +    @wraps(f) +    def wrapper(*args, **kwargs): +        if StressTestsPlugin.enabled: +            raise SkipTest("Stress tests have been disabled") + +        return f(*args, **kwargs) + +    return wrapper + + +def checkSudo(cmd): +    p = subprocess.Popen(['sudo', '-l', '-n'] + cmd, +                         stdin=subprocess.PIPE, stdout=subprocess.PIPE, +                         stderr=subprocess.PIPE) +    out, err = p.communicate() + +    if p.returncode != 0: +        raise SkipTest("Test requires SUDO configuration (%s)" % err.strip()) diff --git a/tests/testrunner.py b/tests/testrunner.py new file mode 100644 index 0000000..1ee7e35 --- /dev/null +++ b/tests/testrunner.py @@ -0,0 +1,308 @@ +# +# Copyright 2014 Red Hat, Inc. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA +# +# Refer to the README and COPYING files for full details of the license +# + +## This framework is mostly copied from vdsm test framework + +import logging +import sys +import os +import unittest +import re +import shutil +import tempfile +from contextlib import contextmanager +from glusternagios import utils +# Monkey patch pthreading in necessary +if sys.version_info[0] == 2: +    # as long as we work with Python 2, we need to monkey-patch threading +    # module before it is ever used. +    import pthreading +    pthreading.monkey_patch() +from nose import config +from nose import core +from nose import result + +from testValidation import SlowTestsPlugin, StressTestsPlugin + + +class TermColor(object): +    black = 30 +    red = 31 +    green = 32 +    yellow = 33 +    blue = 34 +    magenta = 35 +    cyan = 36 +    white = 37 + + +def colorWrite(stream, text, color): +    if os.isatty(stream.fileno()) or os.environ.get("NOSE_COLOR", False): +        stream.write('\x1b[%s;1m%s\x1b[0m' % (color, text)) +    else: +        stream.write(text) + + +@contextmanager +def temporaryPath(perms=None, data=None): +    fd, src = tempfile.mkstemp() +    if data is not None: +        f = os.fdopen(fd, "wb") +        f.write(data) +        f.flush() +        f.close() +    else: +        os.close(fd) +    if perms is not None: +        os.chmod(src, perms) +    try: +        yield src +    finally: +        os.unlink(src) + + +@contextmanager +def namedTemporaryDir(): +    tmpDir = tempfile.mkdtemp() +    try: +        yield tmpDir +    finally: +        shutil.rmtree(tmpDir) + + +# FIXME: This is a forward port of the assertRaises from python +#        2.7, remove when no longer supporting earlier versions +class _AssertRaisesContext(object): +    """A context manager used to implement TestCase.assertRaises* methods.""" + +    def __init__(self, expected, test_case, expected_regexp=None): +        self.expected = expected +        self.failureException = test_case.failureException +        self.expected_regexp = expected_regexp + +    def __enter__(self): +        return self + +    def __exit__(self, exc_type, exc_value, tb): +        if exc_type is None: +            try: +                exc_name = self.expected.__name__ +            except AttributeError: +                exc_name = str(self.expected) +            raise self.failureException( +                "{0} not raised".format(exc_name)) +        if not issubclass(exc_type, self.expected): +            # let unexpected exceptions pass through +            return False +        self.exception = exc_value  # store for later retrieval +        if self.expected_regexp is None: +            return True + +        expected_regexp = self.expected_regexp +        if isinstance(expected_regexp, basestring): +            expected_regexp = re.compile(expected_regexp) +        if not expected_regexp.search(str(exc_value)): +            raise self.failureException('"%s" does not match "%s"' % +                                        (expected_regexp.pattern, +                                         str(exc_value))) +        return True + + +# FIXME: This is a forward port of the assertIn from python +#        2.7, remove when no longer supporting earlier versions +def safe_repr(obj, short=False): +    _MAX_LENGTH = 80 +    try: +        result = repr(obj) +    except Exception: +        result = object.__repr__(obj) +    if not short or len(result) < _MAX_LENGTH: +        return result +    return result[:_MAX_LENGTH] + ' [truncated]...' + + +class PluginsTestCase(unittest.TestCase): +    def __init__(self, *args, **kwargs): +        unittest.TestCase.__init__(self, *args, **kwargs) +        self.log = logging.getLogger(self.__class__.__name__) + +    def retryAssert(self, *args, **kwargs): +        '''Keep retrying an assertion if AssertionError is raised. +           See function utils.retry for the meaning of the arguments. +        ''' +        return utils.retry(expectedException=AssertionError, *args, **kwargs) + +    # FIXME: This is a forward port of the assertRaises from python +    #        2.7, remove when no longer supporting earlier versions +    def assertRaises(self, excClass, callableObj=None, *args, **kwargs): +        context = _AssertRaisesContext(excClass, self) +        if callableObj is None: +            return context +        with context: +            callableObj(*args, **kwargs) + +    # FIXME: This is a forward port of the assertIn from python +    #        2.7, remove when no longer supporting earlier versions +    def assertIn(self, member, container, msg=None): +        """ +        Just like self.assertTrue(a in b), but with a nicer default message. +        """ +        if member not in container: +            if msg is None: +                msg = '%s not found in %s' % (safe_repr(member), +                                              safe_repr(container)) +            raise self.failureException(msg) + +    # FIXME: This is a forward port of the assertNotIn from python +    #        2.7, remove when no longer supporting earlier versions +    def assertNotIn(self, member, container, msg=None): +        """ +        Just like self.assertTrue(a not in b), but with a nicer default message +        """ +        if member in container: +            if msg is None: +                msg = '%s unexpectedly found in %s' % (safe_repr(member), +                                                       safe_repr(container)) +            raise self.failureException(msg) + + +class PluginsTestResult(result.TextTestResult): +    def __init__(self, *args, **kwargs): +        result.TextTestResult.__init__(self, *args, **kwargs) +        self._last_case = None + +    def getDescription(self, test): +        return str(test) + +    def _writeResult(self, test, long_result, color, short_result, success): +        if self.showAll: +            colorWrite(self.stream, long_result, color) +            self.stream.writeln() +        elif self.dots: +            self.stream.write(short_result) +            self.stream.flush() + +    def addSuccess(self, test): +        unittest.TestResult.addSuccess(self, test) +        self._writeResult(test, 'OK', TermColor.green, '.', True) + +    def addFailure(self, test, err): +        unittest.TestResult.addFailure(self, test, err) +        self._writeResult(test, 'FAIL', TermColor.red, 'F', False) + +    def addSkip(self, test, reason): +        # 2.7 skip compat +        from nose.plugins.skip import SkipTest +        if SkipTest in self.errorClasses: +            storage, label, isfail = self.errorClasses[SkipTest] +            storage.append((test, reason)) +            self._writeResult(test, 'SKIP : %s' % reason, TermColor.blue, 'S', +                              True) + +    def addError(self, test, err): +        stream = getattr(self, 'stream', None) +        ec, ev, tb = err +        try: +            exc_info = self._exc_info_to_string(err, test) +        except TypeError: +            # 2.3 compat +            exc_info = self._exc_info_to_string(err) +        for cls, (storage, label, isfail) in self.errorClasses.items(): +            if result.isclass(ec) and issubclass(ec, cls): +                if isfail: +                    test.passed = False +                storage.append((test, exc_info)) +                # Might get patched into a streamless result +                if stream is not None: +                    if self.showAll: +                        message = [label] +                        detail = result._exception_detail(err[1]) +                        if detail: +                            message.append(detail) +                        stream.writeln(": ".join(message)) +                    elif self.dots: +                        stream.write(label[:1]) +                return +        self.errors.append((test, exc_info)) +        test.passed = False +        if stream is not None: +            self._writeResult(test, 'ERROR', TermColor.red, 'E', False) + +    def startTest(self, test): +        unittest.TestResult.startTest(self, test) +        current_case = test.test.__class__.__name__ + +        if self.showAll: +            if current_case != self._last_case: +                self.stream.writeln(current_case) +                self._last_case = current_case + +            self.stream.write( +                '    %s' % str(test.test._testMethodName).ljust(60)) +            self.stream.flush() + + +class PluginsTestRunner(core.TextTestRunner): +    def __init__(self, *args, **kwargs): +        core.TextTestRunner.__init__(self, *args, **kwargs) + +    def _makeResult(self): +        return PluginsTestResult(self.stream, +                                 self.descriptions, +                                 self.verbosity, +                                 self.config) + +    def run(self, test): +        result_ = core.TextTestRunner.run(self, test) +        return result_ + + +def run(): +    argv = sys.argv +    stream = sys.stdout +    verbosity = 3 +    testdir = os.path.dirname(os.path.abspath(__file__)) + +    conf = config.Config(stream=stream, +                         env=os.environ, +                         verbosity=verbosity, +                         workingDir=testdir, +                         plugins=core.DefaultPluginManager()) +    conf.plugins.addPlugin(SlowTestsPlugin()) +    conf.plugins.addPlugin(StressTestsPlugin()) + +    runner = PluginsTestRunner(stream=conf.stream, +                               verbosity=conf.verbosity, +                               config=conf) + +    sys.exit(not core.run(config=conf, testRunner=runner, argv=argv)) + + +def findRemove(listR, value): +    """used to test if a value exist, if it is, return true and remove it.""" +    try: +        listR.remove(value) +        return True +    except ValueError: +        return False + + +if __name__ == '__main__': +    run()  | 
