diff options
author | Bala.FA <barumuga@redhat.com> | 2014-03-07 18:28:09 +0530 |
---|---|---|
committer | Bala.FA <barumuga@redhat.com> | 2014-04-29 10:14:32 +0530 |
commit | 2977b2f34bdbb7284bcc6244e85a1fdb657447f2 (patch) | |
tree | 5e1e49207287b7ed8bddaefa5c6b58d07207ebc0 | |
parent | 4e1a40a920e6b2ee1be9f51b0f2a2f875ca790d3 (diff) |
Initial commitv0.1.0
Change-Id: I45f91b2017ed59b057d21de52fd94c5c83fcf86f
Signed-off-by: Bala.FA <barumuga@redhat.com>
-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() |