diff options
45 files changed, 2670 insertions, 0 deletions
diff --git a/src/ChangeLog b/src/ChangeLog new file mode 100644 index 00000000..b59ce737 --- /dev/null +++ b/src/ChangeLog @@ -0,0 +1,155 @@ +2006-06-19 Steve Conklin <sconklin@tintin> + + * ChangeLog, LICENSE, setup.py, sos.spec: + Added License file and bumped release + +2006-06-08 dlehman <dlehman@tintin> + + * example_plugins/example.py, example_plugins/fsusage.py, example_plugins/release.py, example_plugins/template.py, lib/sos/helpers.py, lib/sos/plugins/apache.py, lib/sos/plugins/bootloader.py, lib/sos/plugins/cluster.py, lib/sos/plugins/filesys.py, lib/sos/plugins/ftp.py, lib/sos/plugins/general.py, lib/sos/plugins/hardware.py, lib/sos/plugins/kernel.py, lib/sos/plugins/ldap.py, lib/sos/plugins/libraries.py, lib/sos/plugins/mail.py, lib/sos/plugins/memory.py, lib/sos/plugins/named.py, lib/sos/plugins/networking.py, lib/sos/plugins/pam.py, lib/sos/plugins/process.py, lib/sos/plugins/rhn.py, lib/sos/plugins/rpm.py, lib/sos/plugins/samba.py, lib/sos/plugins/selinux.py, lib/sos/plugins/squid.py, lib/sos/plugins/startup.py, lib/sos/plugins/system.py, lib/sos/plugins/tarball.py, lib/sos/plugins/x11.py, lib/sos/plugintools.py, lib/sos/policyredhat.py, setup.py, sosreport: + - Flesh out rhn plugin to handle Proxy or Satellite + - Add package queries to policyredhat.py (allPkgsByName, pkgByName, pkgNVRA) + - Add policy instance to the commons dict for access from plugins + - Use string objects' methods instead of the string module where possible + - Remove imports of unused string module + - Cleanup some typos, redundant initializations, &c + +2006-06-08 dlehman <dlehman@tintin> + + * example_plugins/example.py, example_plugins/fsusage.py, example_plugins/release.py, example_plugins/template.py, lib/sos/helpers.py, lib/sos/plugins/apache.py, lib/sos/plugins/bootloader.py, lib/sos/plugins/cluster.py, lib/sos/plugins/filesys.py, lib/sos/plugins/ftp.py, lib/sos/plugins/general.py, lib/sos/plugins/hardware.py, lib/sos/plugins/kernel.py, lib/sos/plugins/ldap.py, lib/sos/plugins/libraries.py, lib/sos/plugins/mail.py, lib/sos/plugins/memory.py, lib/sos/plugins/named.py, lib/sos/plugins/networking.py, lib/sos/plugins/pam.py, lib/sos/plugins/process.py, lib/sos/plugins/rhn.py, lib/sos/plugins/rpm.py, lib/sos/plugins/samba.py, lib/sos/plugins/selinux.py, lib/sos/plugins/squid.py, lib/sos/plugins/startup.py, lib/sos/plugins/system.py, lib/sos/plugins/tarball.py, lib/sos/plugins/x11.py, lib/sos/plugintools.py, lib/sos/policyredhat.py, setup.py, sosreport: + - Flesh out rhn plugin to handle Proxy or Satellite + - Add package queries to policyredhat.py (allPkgsByName, pkgByName, pkgNVRA) + - Add policy instance to the commons dict for access from plugins + - Use string objects' methods instead of the string module where possible + - Remove imports of unused string module + - Cleanup some typos, redundant initializations, &c + +2006-06-05 jwhiter <jwhiter@tintin> + + * lib/sos/plugins/system.py: + adding the abilit to capture the autofs maps to system.py + +2006-05-31 Steve Conklin <sconklin@tintin> + + * ChangeLog, Makefile: New Makefile and ChangeLog (autogenerated) + + * Changelog, setup.py, sos.spec: + Removed old Changelog file and sync'd version and Changelog in spec file + + * lib/sos/plugins/networking.py, TODO, setup.py, sos.spec: + Final patches and version change before submission to Fedora + +2006-05-31 Steve Conklin <sconklin@tintin> + + * Changelog, setup.py, sos.spec: + Removed old Changelog file and sync'd version and Changelog in spec file + + * lib/sos/plugins/networking.py, TODO, setup.py, sos.spec: + Final patches and version change before submission to Fedora + +2006-05-26 Steve Conklin <sconklin@tintin> + + * Changelog, lib/sos/helpers.py, lib/sos/plugintools.py, setup.py, sosreport: + Added pamadio's curses UI for selecting plugin options + Added flushing stdout after informational messages + +2006-05-26 jwhiter <jwhiter@tintin> + + * lib/sos/plugins/filesys.py: + - making the filesys.py plugin call 'blkid' when running at the request of L1, this will allow us to map labels with actual devices. + + * lib/sos/plugins/tarball.py, lib/sos/plugintools.py, sosreport: + - Adding tarball.py to create a tarball of the report after it is run + - Updated sosreport to call postproc() in all the plugins, which handles the post run + - Added runExeInd() which will just run the exe and return the status to plugintools.py + - Added postproc() to plugintools.py so that plugins can implement it + +2006-05-25 Steve Conklin <sconklin@tintin> + + * lib/sos/plugintools.py, sosreport: + Fixed file naming for commands to eliminate special chars and prevent + name collisions. Added sorting of plugins by name before reporting. + + * TODO, lib/sos/plugins/kernel.py, lib/sos/plugintools.py, setup.py: + Fixed option handling + +2006-05-23 jwhiter <jwhiter@tintin> + + * Changelog, lib/sos/plugins/kernel.py, setup.py: + Adding jwb's patch to have sosreport grab sysrq data. + +2006-05-22 Steve Conklin <sconklin@tintin> + + * lib/sos/plugins/apache.py: oops, forgot this file + + * lib/sos/plugins/bootloader.py, lib/sos/plugins/filesys.py, lib/sos/plugins/ftp.py, lib/sos/plugins/general.py, lib/sos/plugins/hardware.py, lib/sos/plugins/kernel.py, lib/sos/plugins/ldap.py, lib/sos/plugins/mail.py, lib/sos/plugins/memory.py, lib/sos/plugins/named.py, lib/sos/plugins/samba.py, lib/sos/plugins/squid.py, lib/sos/plugins/x11.py, sos.spec: + Patch from jwb + + * lib/sos/plugins/filesys.py, lib/sos/plugins/kernel.py: + jwb's patches for kernel.py and filesys.py + + * sosreport: minor fix to the dir perms patch + + * lib/sos/plugins/bootloader.py, lib/sos/plugins/cluster.py, lib/sos/plugins/filesys.py, lib/sos/plugins/general.py, lib/sos/plugins/hardware.py, lib/sos/plugins/kernel.py, lib/sos/plugins/libraries.py, lib/sos/plugins/memory.py, lib/sos/plugins/networking.py, lib/sos/plugins/pam.py, lib/sos/plugins/process.py, lib/sos/plugins/rhn.py, lib/sos/plugins/rpm.py, lib/sos/plugins/selinux.py, lib/sos/plugins/startup.py, lib/sos/plugins/system.py, lib/sos/plugins/template.py, lib/sos/plugins/x11.py, Changelog, example_plugins/template.py, lib/sos/plugintools.py, setup.py, sosreport: + Merged all of jwb's weekend patches. Make output dirs world readable, check before + executing executables, and added a lot of plugins. + +2006-05-19 Steve Conklin <sconklin@tintin> + + * lib/sos/plugins/template.py: Removed unneeded variabled from plugin. + + * Changelog, TODO, example_plugins/example.py, example_plugins/fsusage.py, example_plugins/release.py, example_plugins/runcommand.py, lib/sos/plugins/template.py, lib/sos/plugintools.py, setup.py, sosreport: + Applied jwb's fix, added his examples, improved html output + +2006-05-18 Steve Conklin <sconklin@tintin> + + * example_plugins/example.py, example_plugins/runcommand.py, lib/sos/plugins/template.py: + Put instance variables in plugins in addition to base class + + * example_plugins/example.py, example_plugins/runcommand.py, lib/sos/plugins/template.py, lib/sos/plugintools.py, setup.py, sosreport: + Removed separate pit class, and put everything having to do with the plugin in + pluginBase. Still incorrectly aggregates data across all plugins. + + * README: Added Jwb as a contributor + + * Changelog, TODO, lib/sos/plugins/template.py, lib/sos/plugintools.py, sosreport: + Implemented a base class for plugins + +2006-05-17 Steve Conklin <sconklin@tintin> + + * Changelog, TODO, lib/sos/helpers.py, lib/sos/plugins/template.py, lib/sos/plugintools.py, sosreport, tests/maketesttree.sh: + Cleaned up code, added comments, fixed dir copying bug, changed option + handling. See Changelog + +2006-05-16 Steve Conklin <sconklin@tintin> + + * lib/sos/helpers.py, lib/sos/plugintools.py: + Missed an edit to change log file descriptor to the dictionary. Fixed. + + * TODO: Added documentation to list + + * TODO: Added need for example plugin + +2006-05-15 Steve Conklin <sconklin@tintin> + + * README, TODO, lib/sos/plugins/template.py, lib/sos/plugintools.py, setup.py, sosreport: + Added a dictionary of things that need to be known to all, like paths for + reports. + + Added Pierre Amadio's command line arg handling + + Fixed incorrect handling of command completion status + + Added html generation + +2006-05-09 Steve Conklin <sconklin@tintin> + + * TODO: changed it + + * setup.cfg: removed RFC file + + * MANIFEST.in, Notes.txt, README, TODO, lib/sos/__init__.py, lib/sos/helpers.py, lib/sos/plugins/__init__.py, lib/sos/plugins/template.py, lib/sos/plugintools.py, lib/sos/policyredhat.py, setup.cfg, setup.py, sosreport: + Initial checkin of the sos project + + * MANIFEST.in, Notes.txt, README, TODO, lib/sos/__init__.py, lib/sos/helpers.py, lib/sos/plugins/__init__.py, lib/sos/plugins/template.py, lib/sos/plugintools.py, lib/sos/policyredhat.py, setup.cfg, setup.py, sosreport: + New file. + diff --git a/src/LICENSE b/src/LICENSE new file mode 100644 index 00000000..7a8e8abf --- /dev/null +++ b/src/LICENSE @@ -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 Lesser General +Public License instead of this License. diff --git a/src/MANIFEST.in b/src/MANIFEST.in new file mode 100644 index 00000000..11193668 --- /dev/null +++ b/src/MANIFEST.in @@ -0,0 +1,4 @@ +# NOTE: Including sosreport here is a hack. This +# is done because the data_files handling from setup.py +# is broken for building dists (at least in Python 2.3) +include README TODO sosreport MANIFEST.in diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 00000000..e6387672 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,46 @@ +# +# Makefile for sos system support tools +# + +NAME = sos +VERSION = $(shell awk '/define version/ { print $$3 }' sos.spec) +RELEASE = $(shell awk '/define release/ { print $$3 }' sos.spec) +CVSTAG = r$(subst .,-,$(VERSION)-$(RELEASE)) +CVSROOT = $(shell cat CVS/Root) + + +all: + +changelog: + @rcs2log | sed "s|@.*redhat\.com|@redhat.com|" | sed "s|@.*redhat\.de|@redhat.com|" | sed "s|@redhat\.de|@redhat.com|" | sed "s|@@|@|" | \ + sed "s|/usr/local/CVS/$(NAME)/||g" | sed "s|/cvs/rhl/$(NAME)/||g" > changenew + mv ChangeLog ChangeLog.old + cat changenew ChangeLog.old > ChangeLog + rm -f changenew + +tag-archive: + @cvs -Q tag -F $(CVSTAG) + echo "$(CVSTAG)" + +create-archive: tag-archive + @rm -rf /tmp/$(NAME) + @cd /tmp; cvs -Q -d $(CVSROOT) export -r$(CVSTAG) $(NAME) || echo GRRRrrrrr -- ignore [export aborted] + @mv /tmp/$(NAME) /tmp/$(NAME)-$(VERSION) + @cd /tmp; tar --bzip2 -cSpf $(NAME)-$(VERSION).tar.bz2 $(NAME)-$(VERSION) + @rm -rf /tmp/$(NAME)-$(VERSION) + @cp /tmp/$(NAME)-$(VERSION).tar.bz2 . + @rm -f /tmp/$(NAME)-$(VERSION).tar.bz2 + @echo " " + @echo "The final archive is ./$(NAME)-$(VERSION).tar.bz2." + +archive: clean tag-archive create-archive + +install: + python setup.py install + +version: + @echo "The version is $(NAME)-$(VERSION)-$(RELEASE)" + + +clean: + @rm -fv *~ .*~ changenew ChangeLog.old $(NAME)-$(VERSION)-$(RELEASE).tar.bz2 diff --git a/src/README b/src/README new file mode 100644 index 00000000..0f6a301e --- /dev/null +++ b/src/README @@ -0,0 +1,15 @@ +This set of tools is designed to provide information to support +organizations in an extensible manner, allowing third parties, +package maintainers, and anyone else to provide plugins that will +collect, analyze, and report information that is useful for supporting +software packages. + +(all the following as root) +to install locally ==> python setup.py install +to build an rpm ==> python setup.py bdist_rpm + + +Contributors: +Steve Conklin <sconklin@redhat.com> +Pierre Amadio <pamadio@redhat.com> +John Berninger <jwb@redhat.com> diff --git a/src/TODO b/src/TODO new file mode 100644 index 00000000..ebb0e9bc --- /dev/null +++ b/src/TODO @@ -0,0 +1,25 @@ +To Do List: + +When a directory and all below it is copied: + 1. the targets of symlinks is not copied + 2. Absolute symlinks are not corrected to point into the destination tree. + +FIX - When a directory includes a proc file system, copying that tree hangs - +example is in named.py when running a chrooted named. + +ADD - allow each plugin to optionally not load, and to be able to test whether +other packages are installed. For example, if apache isn't installed, don't +load the apache plugin. + +Documentation - man page, plugin howto doc, inline doc in plugin template + +review and test error handling for things like a full tmp file system + +Make the [ OK ] type completion messages pretty and correct - see helpers.py + + + + + + + diff --git a/src/example_plugins/example.py b/src/example_plugins/example.py new file mode 100755 index 00000000..bf461c44 --- /dev/null +++ b/src/example_plugins/example.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python + +## example.py +## An example sos plugin + +## Copyright (C) 2006 Steve Conklin <sconklin@redhat.com> + +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +# Class name must be the same as file name and method names must not change +class example(sos.plugintools.PluginBase): + """This is an example plugin for sos. Plugins gather, analyze, and report on various aspects + of system operation that are of interest. plugins are based on the PluginBase class, which + you should inspect if you wish to override any methods in your plugin. The methods of use + to plugin developers are: + collect() - use the functions sosCp and sosRunExe to gether information + analyze() - perform any special analysis you require beyond just saving the + information gathered by collect(). Use sosAlert() and sosAddCustomText() + to add information to the report. + report() - override this method if you wish to replace the default reporting + + All plugins will use collect(), some will use analyze(), few will override report() + """ + optionList = [] + copiedFiles = [] + copiedDirs = [] + executedCommands = [] + alerts = [] + customText = "" + cInfo = None + piName = None + optNames = [] + optParms = [] + + # Add your options here, indicate whether they are slow to run, and set whether they are enabled by default + # Options are dictionaries that conatin a short name, long desc, speed, and whether they are enabled by default + optionList = [("init.d", 'Gathers the init.d directory', 'slow', 0), + ('Option 2', 'Gathers information about each follicle on every toe', 'slow', 0), + ('Option 3', 'Gathers toenail polish color', 'fast', 0)] + + def collect(self): + ''' First phase - Collect all the information we need. + Directories are copied recursively. arbitrary commands may be + executed using the susRunExe method. Information is automatically saved, and + links are presented in the report to each file or directory which has been + copied to the saved tree. Also, links are provided to the output from each command. + ''' + # Here's how to copy files and directory trees + self.copyFileOrDir("/etc/hosts") + # this one saves a file path to the copy for later analysis + self.fooFilePath = self.copyFileOrDir("/proc/cpuinfo") + + # Here's how to test your options and execute if enabled + if self.isOptionEnabled("init.d"): + self.copyFileOrDir("/etc/init.d") # copies a whole directory tree + + # Here's how to execute a command + # you can save the path to the copied file for later analysis if desired + self.psCmdDstFileName = self.runExe("/bin/ps -ef") + return + + def analyze(self): + ''' This is optional and need not be defined. + If you wish to perform some analysis on either files + that were gathered or on the output of commands, then save the filenames on the + destination file system when gathering that information in the collect() method + and use them here + ''' + # This is an example of opening and reading the output of a command that + # was run in the collect() method. Note that the output of the command is + # included in the report anyway + fd = open(self.fooFilePath) + lines = fd.readlines() + fd.close() + for line in lines: + if line.count("vendor_id"): + self.addCustomText("Vendor ID string is: %s <br>\n" % line) + # + # Alerts can optionally be generated, and will be included in the + # report automatically + # + self.addAlert("This is an alert") + return + +# def report(self): +# """ Usually, this doesn't even need to be defined, and you can inherit the +# base class, unless you want to replace what sosGetResults() +# does with your own custom report generator. If you are going to do that, have a good +# look at that method to see what it does. Custom text and alerts can still be added +# here using sosAddCustomText() and sosAddAlert() +# This method returns html that will be included inline in the report +# """ + + diff --git a/src/example_plugins/fsusage.py b/src/example_plugins/fsusage.py new file mode 100644 index 00000000..898aaa12 --- /dev/null +++ b/src/example_plugins/fsusage.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +# Class name must be the same as file name and method names must not change +class fsusage(sos.plugintools.PluginBase): + def collect(self): + self.psCmdDstFileName = self.runExe("/bin/df -al") + return diff --git a/src/example_plugins/release.py b/src/example_plugins/release.py new file mode 100644 index 00000000..8ef395b5 --- /dev/null +++ b/src/example_plugins/release.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +# Class name must be the same as file name and method names must not change +class release(sos.plugintools.PluginBase): + def collect(self): + self.copyFileOrDir("/etc/redhat-release") + return diff --git a/src/example_plugins/runcommand.py b/src/example_plugins/runcommand.py new file mode 100755 index 00000000..fa16020e --- /dev/null +++ b/src/example_plugins/runcommand.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python + +## runcommand.py +## An example plugin for sos + +## Copyright (C) 2006 Steve Conklin <sconklin@redhat.com> + +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +# Class name must be the same as file name and method names must not change +class runcommand(sos.plugintools.PluginBase): + """This is a very simple example plugin that just runs one command in a shell. That + command could be a script supplied with your package which outputs information of interest + to support. When the script or command is run, stdout is collected and included in the + report generated by sosreport, and stderr is collected and copied into the sos log. + + This is useful for people who have minimal knowledge of python, who wish to write + collection tools in other languages, or who have existing tools. + + If your script or command generates output files that you want included in the sosreport + collection of files, include sosCp calls to include them. + + The only method required for this simple plugin is collect(). + + Your finished plugin should be included with your package and installed in python's + site-packages/sos/plugins/ directory + """ + optionList = [] + copiedFiles = [] + copiedDirs = [] + executedCommands = [] + alerts = [] + customText = "" + cInfo = None + piName = None + optNames = [] + optParms = [] + + def collect(self): + ''' Run a command. Output is automatically included in the report. + ''' + self.runExe("/path/to/my/script --myoption --anotheroption") + + # if (for example) that command created files /foo/bar/baz.txt and + # we want to include that in our report, we include the next line: + #self.pit.sosCp("/foo/bar/baz.txt") diff --git a/src/example_plugins/template.py b/src/example_plugins/template.py new file mode 100755 index 00000000..f8ed0e35 --- /dev/null +++ b/src/example_plugins/template.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python + +## template.py +## A template for sos plugins + +## Copyright (C) 2006 Steve Conklin <sconklin@redhat.com> + +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +# Class name must be the same as file name and method names must not change +class template(sos.plugintools.PluginBase): + """This is a template plugin for sos. Plugins gather, analyze, and report on various aspects + of system operation that are of interest. plugins are based on the PluginBase class, which + you should inspect if you wish to override any methods in your plugin. The methods of use + to plugin developers are: + collect() - use the functions sosCp and sosRunExe to gether information + analyze() - perform any special analysis you require beyond just saving the + information gathered by collect(). Use sosAlert() and sosAddCustomText() + to add information to the report. + report() - override this method if you wish to replace the default reporting + + All plugins will use collect(), some will use analyze(), few will override report() + """ + + # Add your options here, indicate whether they are slow to run, and set whether they are enabled by default + # Options are dictionaries that conatin a short name, long desc, speed, and whether they are enabled by default + optionList = [("init.d", 'Gathers the init.d directory', 'slow', 0), + ('Option 2', 'Gathers information about each follicle on every toe', 'slow', 0), + ('Option 3', 'Gathers toenail polish color', 'fast', 0)] + + def collect(self): + ''' First phase - Collect all the information we need. + Directories are copied recursively. arbitrary commands may be + executed using the susRunExe method. Information is automatically saved, and + links are presented in the report to each file or directory which has been + copied to the saved tree. Also, links are provided to the output from each command. + ''' + # For this example, we use files created in our build test directory. Edit the + # following line after running the maketesttree.sh script + testdir = "/home/sconklin/src/sos/tests/tree/" + self.copyFileOrDir(testdir + "absdirlink") + self.copyFileOrDir(testdir + "bar") + + # Here's how to test your options and execute if enabled + if self.isOptionEnabled("init.d"): + self.copyFileOrDir("/etc/init.d") + self.copyFileOrDir(testdir + "abslink") + # you can save the path to the copied file for later analysis if desired + self.fooFilePath = self.copyFileOrDir(testdir + "abslink2") + self.copyFileOrDir(testdir + "abslink3") + self.psCmdDstFileName = self.runExe("/bin/ps -ef") + return + + def analyze(self): + ''' This is optional and need not be defined. + If you wish to perform some analysis on either files + that were gathered or on the output of commands, then save the filenames on the + destination file system when gathering that information in the collect() method + and use them here + ''' + # This is an example of opening and reading the output of a command that + # was run in the collect() method. Note that the output of the command is + # included in the report anyway + fd = open(self.psCmdDstFileName) + lines = fd.readlines() + fd.close() + procs = 0 + for line in lines: + # can perform analysis here - This is a dumb example, but + # shows how to add customized text to output + if line.count("sconkli"): + procs = procs + 1 + self.addCustomText("sconklin has %d processes running <br>\n" % procs) + # + # Alerts can optionally be generated, and will be included in the + # report automatically + # + self.addAlert("This is an alert") + return + +# def report(self): +# """ Usually, this doesn't even need to be defined, and you can inherit the +# base class, unless you want to replace what sosGetResults() +# does with your own custom report generator. If you are going to do that, have a good +# look at that method to see what it does. Custom text and alerts can still be added +# here using sosAddCustomText() and sosAddAlert() +# This method returns html that will be included inline in the report +# """ + + diff --git a/src/lib/sos/__init__.py b/src/lib/sos/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/lib/sos/__init__.py diff --git a/src/lib/sos/helpers.py b/src/lib/sos/helpers.py new file mode 100755 index 00000000..447c164f --- /dev/null +++ b/src/lib/sos/helpers.py @@ -0,0 +1,140 @@ +## helpers.py +## Implement policies required for the sos system support tool + +## Copyright (C) 2006 Steve Conklin <sconklin@redhat.com> + +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +## Some code adapted from "Python Cookbook, 2nd ed", by Alex +## Martelli, Anna Martelli Ravenscroft, and David Ascher +## (O'Reilly Media, 2005) 0-596-00797-3 +## + +import os, popen2, fcntl, select, itertools, sys +from tempfile import mkdtemp + +workingBase = None + +def importPlugin(pluginname, name): + """ Import a plugin to extend capabilities of sosreport + """ + try: + plugin = __import__(pluginname, globals(), locals(), [name]) + except ImportError: + return None + return getattr(plugin, name) + + +def sosFindTmpDir(): + """Find a temp directory to form the root for our gathered information + and reports. + """ + workingBase = mkdtemp("","sos_") + return workingBase + + +def makeNonBlocking(fd): + """ Make the file desccriptor non-blocking. This prevents deadlocks. + """ + fl = fcntl.fcntl(fd, fcntl.F_GETFL) + try: + fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NDELAY) + except AttributeError: + fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.FNDELAY) + + +def sosGetCommandOutput(command): + """ Execute a command and gather stdin, stdout, and return status. + Adapted from Python Cookbook - O'Reilly + """ + child = popen2.Popen3(command, 1) # Capture stdout and stderr from command + child.tochild.close() # don't need to write to child's stdin + outfile = child.fromchild + outfd = outfile.fileno() + errfile = child.childerr + errfd = errfile.fileno() + makeNonBlocking(outfd) # Don't deadlock! Make fd's nonblocking. + makeNonBlocking(errfd) + outdata, errdata = [], [] + outeof = erreof = False + while True: + to_check = [outfd]*(not outeof) + [errfd]*(not erreof) + ready = select.select(to_check, [], []) # Wait for input + if outfd in ready[0]: + outchunk = outfile.read() + if outchunk == '': + outeof = True + else: + outdata.append(outchunk) + if errfd in ready[0]: + errchunk = errfile.read() + if errchunk == '': + erreof = True + else: + errdata.append(errchunk) + if outeof and erreof: + break + select.select([],[],[],.1) # Allow a little time for buffers to fill + err = child.wait() + return (err, ''.join(outdata), ''.join(errdata)) + + +# TODO - this needs to be made clean and moved to the plugin tools, so +# that it prints nice color output like sysreport +def sosStatus(stat): + """ Complete a status line that has been output to the console, + providing pass/fail indication. + """ + if not stat: + print " [ OK ]" + else: + print " [ FAILED ]" + sys.stdout.flush() + return + + +def allEqual(elements): + ''' return True if all the elements are equal, otherwise False. ''' + first_element = elements[0] + for other_element in elements[1:]: + if other_element != first_element: return False + return True + + +def commonPrefix(*sequences): + ''' return a list of common elements at the start of all sequences, + then a list of lists that are the unique tails of each sequence. ''' + # if there are no sequences at all, we're done + if not sequences: return [], [] + # loop in parallel on the sequences + common = [] + for elements in itertools.izip(*sequences): + # unless all elements are equal, bail out of the loop + if not allEqual(elements): break + # got one more common element, append it and keep looping + common.append(elements[0]) + # return the common prefix and unique tails + return common, [ sequence[len(common):] for sequence in sequences ] + +def sosRelPath(p1, p2, sep=os.path.sep, pardir=os.path.pardir): + ''' return a relative path from p1 equivalent to path p2. + In particular: the empty string, if p1 == p2; + p2, if p1 and p2 have no common prefix. + ''' + common, (u1, u2) = commonPrefix(p1.split(sep), p2.split(sep)) + if not common: + return p2 # leave path absolute if nothing at all in common + return sep.join( [pardir]*len(u1) + u2 ) + diff --git a/src/lib/sos/plugins/__init__.py b/src/lib/sos/plugins/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/lib/sos/plugins/__init__.py diff --git a/src/lib/sos/plugins/apache.py b/src/lib/sos/plugins/apache.py new file mode 100644 index 00000000..6a3e35ea --- /dev/null +++ b/src/lib/sos/plugins/apache.py @@ -0,0 +1,24 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class apache(sos.plugintools.PluginBase): + """This plugin gathers Apache related information + """ + def collect(self): + self.copyFileOrDir("/etc/httpd/conf/httpd.conf") + self.copyFileGlob("/etc/httpd/conf.d/*.conf") + return + diff --git a/src/lib/sos/plugins/bootloader.py b/src/lib/sos/plugins/bootloader.py new file mode 100644 index 00000000..06d653a8 --- /dev/null +++ b/src/lib/sos/plugins/bootloader.py @@ -0,0 +1,31 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class bootloader(sos.plugintools.PluginBase): + """This plugin gathers bootloader information + """ + def collect(self): + self.copyFileOrDir("/etc/lilo.conf") + self.copyFileOrDir("/etc/milo.conf") + self.copyFileOrDir("/etc/silo.conf") + self.copyFileOrDir("/boot/grub/grub.conf") + self.copyFileOrDir("/boot/grub/device.map") + self.copyFileOrDir("/boot/efi/elilo.conf") + self.copyFileOrDir("/boot/yaboot.conf") + + self.runExe("/sbin/lilo -q") + return + diff --git a/src/lib/sos/plugins/cluster.py b/src/lib/sos/plugins/cluster.py new file mode 100644 index 00000000..35f7e9a9 --- /dev/null +++ b/src/lib/sos/plugins/cluster.py @@ -0,0 +1,25 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class cluster(sos.plugintools.PluginBase): + """This plugin gathers cluster related information + """ + def collect(self): + self.copyFileOrDir("/etc/cluster.conf") + self.copyFileOrDir("/etc/cluster.xml") + self.copyFileOrDir("/etc/cluster") + return + diff --git a/src/lib/sos/plugins/filesys.py b/src/lib/sos/plugins/filesys.py new file mode 100644 index 00000000..71859047 --- /dev/null +++ b/src/lib/sos/plugins/filesys.py @@ -0,0 +1,46 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools +import commands + +class filesys(sos.plugintools.PluginBase): + """This plugin gathers infomraiton on filesystems + """ + def collect(self): + self.copyFileOrDir("/proc/filesystems") + self.copyFileOrDir("/etc/fstab") + self.copyFileOrDir("/proc/mounts") + self.copyFileOrDir("/proc/mdstat") + self.copyFileOrDir("/etc/raidtab") + self.copyFileOrDir("/etc/mdadm.conf") + self.copyFileOrDir("/etc/auto.master") + self.copyFileOrDir("/etc/auto.misc") + self.copyFileOrDir("/etc/auto.net") + + self.runExe("/bin/df -al") + self.runExe("/usr/sbin/lsof -b +M -n -l") + self.runExe("/bin/mount -l") + self.runExe("/sbin/blkid") + + raiddevs = commands.getoutput("/bin/cat /proc/partitions | /bin/egrep -v \"^major|^$\" | /bin/awk '{print $4}' | /bin/grep \/ | /bin/egrep -v \"p[0123456789]$\"") + disks = commands.getoutput("/bin/cat /proc/partitions | /bin/egrep -v \"^major|^$\" | /bin/awk '{print $4}' | /bin/grep -v / | /bin/egrep -v \"[0123456789]$\"") + for disk in raiddevs.split('\n'): + if '' != disk.strip(): + self.runExe("/sbin/fdisk -l /dev/%s 2>&1" % (disk,)) + for disk in disks.split('\n'): + if '' != disk.strip(): + self.runExe("/sbin/fdisk -l /dev/%s 2>&1" % (disk,)) + return + diff --git a/src/lib/sos/plugins/ftp.py b/src/lib/sos/plugins/ftp.py new file mode 100644 index 00000000..f1c80304 --- /dev/null +++ b/src/lib/sos/plugins/ftp.py @@ -0,0 +1,24 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class ftp(sos.plugintools.PluginBase): + """This plugin gathers FTP server related information + """ + def collect(self): + self.copyFileGlob("/etc/ftp*") + self.copyFileOrDir("/etc/vsftpd") + return + diff --git a/src/lib/sos/plugins/general.py b/src/lib/sos/plugins/general.py new file mode 100644 index 00000000..9a9544a7 --- /dev/null +++ b/src/lib/sos/plugins/general.py @@ -0,0 +1,35 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class general(sos.plugintools.PluginBase): + """This plugin gathers very basic system information + """ + def collect(self): + self.copyFileOrDir("/etc/redhat-release") + self.copyFileOrDir("/etc/sysconfig") + self.copyFileOrDir("/proc/stat") + self.copyFileOrDir("/var/log/dmesg") + self.copyFileOrDir("/var/log/messages") + self.copyFileOrDir("/var/log/sa") + self.copyFileOrDir("/var/log/secure") + self.copyFileOrDir("/var/log/up2date") + self.copyFileOrDir("/etc/exports") + self.copyFileGlob("/etc/cups/*.conf") + self.runExe("/bin/hostname") + self.runExe("/bin/date") + self.runExe("/usr/bin/uptime") + return + diff --git a/src/lib/sos/plugins/hardware.py b/src/lib/sos/plugins/hardware.py new file mode 100644 index 00000000..7f2b075b --- /dev/null +++ b/src/lib/sos/plugins/hardware.py @@ -0,0 +1,50 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools +import commands + +class hardware(sos.plugintools.PluginBase): + """This plugin gathers hardware related information + """ + def collect(self): + self.copyFileOrDir("/proc/partitions") + self.copyFileOrDir("/proc/cpuinfo") + self.copyFileOrDir("/proc/meminfo") + self.copyFileOrDir("/proc/ioports") + self.copyFileOrDir("/proc/interrupts") + self.copyFileOrDir("/proc/scsi") + self.copyFileOrDir("/proc/dma") + self.copyFileOrDir("/proc/devices") + self.copyFileOrDir("/proc/rtc") + self.copyFileOrDir("/proc/ide") + self.copyFileOrDir("/proc/bus") + self.copyFileOrDir("/etc/stinit.def") + self.copyFileOrDir("/etc/sysconfig/hwconf") + self.copyFileOrDir("/proc/chandev") + self.copyFileOrDir("/proc/dasd") + self.copyFileOrDir("/proc/s390dbf/tape") + self.runExe("/usr/share/rhn/up2dateclient/hardware.py") + self.runExe("/sbin/lspci -vvn") + self.runExe("dmesg | grep -e 'e820.' -e 'agp.'") + + for hwmodule in commands.getoutput('cat pcitable | grep -v "Card:" | awk \'{ gsub("\"","",$0); { print $NF; };} \' | uniq -u'): + cmdToRun = "dmesg | grep %s" % (hwmodule,) + self.runExe(cmdToRun) + + self.runExe("/usr/sbin/vgdisplay -vv") + self.runExe("/sbin/lsusb") + self.runExe("/usr/bin/lshal") + return + diff --git a/src/lib/sos/plugins/kernel.py b/src/lib/sos/plugins/kernel.py new file mode 100644 index 00000000..064a8314 --- /dev/null +++ b/src/lib/sos/plugins/kernel.py @@ -0,0 +1,61 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools +import commands, os + +class kernel(sos.plugintools.PluginBase): + """This plugin gathers kernel related information + """ + optionList = [("modinfo", 'Gathers module information on all modules', 'fast', 1), + ('sysrq', 'Trigger SysRq dumps', 'fast', 1)] + + def collect(self): + self.runExe("/bin/uname -a") + self.runExe("/sbin/lsmod") + if self.isOptionEnabled('modinfo'): + for kmod in commands.getoutput('/sbin/lsmod | /bin/cut -f1 -d" " 2>/dev/null | /bin/grep -v Module 2>/dev/null').split('\n'): + if '' != kmod.strip(): + runcmd = "/sbin/modinfo %s" % (kmod,) + self.runExe(runcmd) + self.runExe("/sbin/ksyms") + self.copyFileOrDir("/proc/filesystems") + self.copyFileOrDir("/proc/ksyms") + self.copyFileOrDir("/proc/slabinfo") + kver = commands.getoutput('/bin/uname -r') + depfile = "/lib/modules/%s/modules.dep" % (kver,) + self.copyFileOrDir(depfile) + self.copyFileOrDir("/etc/conf.modules") + self.copyFileOrDir("/etc/modules.conf") + self.copyFileOrDir("/etc/modprobe.conf") + self.runExe("/usr/sbin/dmidecode") + self.runExe("/usr/sbin/dkms status") + self.copyFileOrDir("/proc/cmdline") + self.copyFileOrDir("/proc/driver") + # trigger some sysrq's. I'm not sure I like doing it this way, but + # since we end up with the sysrq dumps in syslog whether we run the + # syslog report before or after this, I suppose I can live with it. + if self.isOptionEnabled('sysrq') and os.access("/proc/sysrq-trigger", os.W_OK) and os.access("/proc/sys/kernel/sysrq", os.R_OK): + sysrq_state = commands.getoutput("/bin/cat /proc/sys/kernel/sysrq") + commands.getoutput("/bin/echo 1 > /proc/sys/kernel/sysrq") + for key in ['m', 'p', 't']: + commands.getoutput("/bin/echo %s > /proc/sysrq-trigger" % (key,)) + commands.getoutput("/bin/echo %s > /proc/sys/kernel/sysrq" % (sysrq_state,)) + # No need to grab syslog here if we can't trigger sysrq, so keep this + # inside the if + self.copyFileGlob("/var/log/messages*") + + + return + diff --git a/src/lib/sos/plugins/ldap.py b/src/lib/sos/plugins/ldap.py new file mode 100644 index 00000000..4a353a26 --- /dev/null +++ b/src/lib/sos/plugins/ldap.py @@ -0,0 +1,24 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class ldap(sos.plugintools.PluginBase): + """This plugin gathers LDAP related information + """ + def collect(self): + self.copyFileOrDir("/etc/ldap.conf") + self.copyFileOrDir("/etc/openldap") + return + diff --git a/src/lib/sos/plugins/libraries.py b/src/lib/sos/plugins/libraries.py new file mode 100644 index 00000000..f6adf89b --- /dev/null +++ b/src/lib/sos/plugins/libraries.py @@ -0,0 +1,24 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class libraries(sos.plugintools.PluginBase): + """This plugin gathers information on shared libraries + """ + def collect(self): + self.copyFileOrDir("/etc/ld.so.conf") + self.copyFileOrDir("/etc/ld.so.conf.d") + return + diff --git a/src/lib/sos/plugins/mail.py b/src/lib/sos/plugins/mail.py new file mode 100644 index 00000000..8945550d --- /dev/null +++ b/src/lib/sos/plugins/mail.py @@ -0,0 +1,25 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class mail(sos.plugintools.PluginBase): + """This plugin gathers mail server related information + """ + def collect(self): + self.copyFileOrDir("/etc/mail") + self.copyFileOrDir("/etc/postfix/main.cf") + self.copyFileOrDir("/etc/postfix/master.cf") + return + diff --git a/src/lib/sos/plugins/memory.py b/src/lib/sos/plugins/memory.py new file mode 100644 index 00000000..0e6d6a60 --- /dev/null +++ b/src/lib/sos/plugins/memory.py @@ -0,0 +1,27 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class memory(sos.plugintools.PluginBase): + """This plugin gathers memory usage information + """ + def collect(self): + self.copyFileOrDir("/proc/pci") + self.copyFileOrDir("/proc/meminfo") + + self.runExe("/bin/dmesg | grep -e 'e820.' -e 'aperature.'") + self.runExe("/usr/bin/free") + return + diff --git a/src/lib/sos/plugins/named.py b/src/lib/sos/plugins/named.py new file mode 100644 index 00000000..7d77c40d --- /dev/null +++ b/src/lib/sos/plugins/named.py @@ -0,0 +1,34 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools +import commands +import os + +class named(sos.plugintools.PluginBase): + """This plugin gathers named related information + """ + def collect(self): + dnsdir = "" + self.copyFileOrDir("/etc/named.boot") + self.copyFileOrDir("/etc/named.conf") + if os.access("/etc/named.conf", os.R_OK): + dnsdir = commands.getoutput("/bin/grep -i directory /etc/named.conf | /bin/gawk '{print $2}' | /bin/sed 's/\\\"//g' | /bin/sed 's/\;//g'") + if os.access("/etc/named.boot", os.R_OK): + dnsdir = commands.getoutput("/bin/grep -i directory /etc/named.boot | /bin/gawk '{print $2}' | /bin/sed 's/\\\"//g' | /bin/sed 's/\;//g'") + if '' != dnsdir.strip(): + print "FIX named.py - hangs when named chrooted because of /var/named/chroot/proc" + #self.copyFileOrDir(dnsdir) + return + diff --git a/src/lib/sos/plugins/networking.py b/src/lib/sos/plugins/networking.py new file mode 100644 index 00000000..f6a8fdb0 --- /dev/null +++ b/src/lib/sos/plugins/networking.py @@ -0,0 +1,58 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools +import os,re + +class networking(sos.plugintools.PluginBase): + """This plugin gathers network related information + """ + + def get_interface_name(self,ifconfigFile): + """Return a dictionnary for wich key are intefrace name according to the + output of ifcongif-a stored in ifconfigFile. + """ + out={} + if(os.path.isfile(ifconfigFile)): + f=open(ifconfigFile,'r') + content=f.read() + f.close() + reg=re.compile(r"^(eth\d+)\D",re.MULTILINE) + for name in reg.findall(content): + out[name]=1 + return out + + + def collect(self): + self.copyFileOrDir("/etc/nsswitch.conf") + self.copyFileOrDir("/etc/yp.conf") + self.copyFileOrDir("/etc/inetd.conf") + self.copyFileOrDir("/etc/xinetd.conf") + self.copyFileOrDir("/etc/xinetd.d") + self.copyFileGlob("/etc/host*") + self.copyFileOrDir("/etc/resolv.conf") + # self.copyFileOrDir("/etc/sysconfig/iptables-config") + # The above is redundant + ifconfigFile=self.runExe("/sbin/ifconfig -a") + self.runExe("/sbin/route -n") + self.runExe("/sbin/ipchains -nvL") + self.runExe("/sbin/iptables -t filter -nvL") + self.runExe("/sbin/iptables -t nat -nvL") + self.runExe("/sbin/iptables -t mangle -nvL") + if ifconfigFile: + for eth in self.get_interface_name(ifconfigFile): + self.runExe("/sbin/ethtool "+eth) + + return + diff --git a/src/lib/sos/plugins/pam.py b/src/lib/sos/plugins/pam.py new file mode 100644 index 00000000..adce0046 --- /dev/null +++ b/src/lib/sos/plugins/pam.py @@ -0,0 +1,23 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class pam(sos.plugintools.PluginBase): + """This plugin gathers PAM related information + """ + def collect(self): + self.copyFileOrDir("/etc/pam.d") + return + diff --git a/src/lib/sos/plugins/process.py b/src/lib/sos/plugins/process.py new file mode 100644 index 00000000..d360af10 --- /dev/null +++ b/src/lib/sos/plugins/process.py @@ -0,0 +1,24 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class process(sos.plugintools.PluginBase): + """This plugin gathers process information + """ + def collect(self): + self.runExe("/bin/ps auxww") + self.runExe("/usr/bin/pstree") + return + diff --git a/src/lib/sos/plugins/rhn.py b/src/lib/sos/plugins/rhn.py new file mode 100644 index 00000000..512e0d7d --- /dev/null +++ b/src/lib/sos/plugins/rhn.py @@ -0,0 +1,86 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +from sos.plugintools import PluginBase + +class rhn(PluginBase): + """This plugin gathers RHN server related information + """ + def collect(self): + # XXX check for the presence of requisite packages + satellite = self.cInfo["policy"].pkgByName("rhns-satellite-tools") + proxy = self.cInfo["policy"].pkgByName("rhns-proxy-tools") + if not satellite and not proxy: + return + + # + # First, grab things needed from both Satellite and Proxy systems + # + # TODO: add chain load so we can use existing modules for httpd, &c. + # + + # basic RHN logs and configs + self.copyFileGlob("/var/log/rhn*") + self.copyFileOrDir("/etc/rhn") + self.runExe("/usr/share/rhn/up2date_client/hardware.py") + + # httpd + self.copyFileOrDir("/etc/httpd/conf") + self.copyFileOrDir("/var/log/httpd") + + # RPM manifests + self.runExe("/bin/rpm -qa --last | sort") + + # monitoring scout logs + self.copyFileGlob("/home/nocpulse/var/*.log*") + self.copyFileGlob("/home/nocpulse/var/commands/*.log*") + + # + # Now, go for product-specific data + # + if satellite: + self.collectSatellite(satellite) + + if proxy: + self.collectProxy(proxy) + + def collectSatellite(self, satellite): + self.runExe("/usr/bin/rhn-schema-version") + self.runExe("/usr/bin/rhn-charsets") + + # oracle + self.copyFileOrDir("/etc/tnsnames.ora") + + # tomcat (4.x and newer satellites only) + if not self.cInfo["policy"].pkgNVRA(satellite)[1].startswith("3."): + self.copyFileOrDir("/etc/tomcat5") + self.copyFileOrDir("/var/log/tomcat5") + + # jabberd + # - logs to /var/log/messages + self.copyFileOrDir("/etc/jabberd") + + # SSL build + self.copyFileOrDir("/root/ssl-build") + + # monitoring logs + self.copyFileGlob("/opt/notification/var/*.log*") + self.copyFileGlob("/var/tmp/ack_handler.log*") + self.copyFileGlob("/var/tmp/enqueue.log*") + + def collectProxy(self, proxy): + # squid + self.copyFileOrDir("/etc/squid") + self.copyFileOrDir("/var/log/squid") + diff --git a/src/lib/sos/plugins/rpm.py b/src/lib/sos/plugins/rpm.py new file mode 100644 index 00000000..44b9d5c8 --- /dev/null +++ b/src/lib/sos/plugins/rpm.py @@ -0,0 +1,32 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class rpm(sos.plugintools.PluginBase): + """This plugin gathers RPM information + """ + optionList = [("rpmq", "Queries for package information via rpm -q", "fast", 1), + ("rpmva", "Runs a verify on all packages", "slow", 0)] + + def collect(self): + self.copyFileOrDir("/var/log/rpmpkgs") + + if self.isOptionEnabled("rpmq"): + self.runExe("/bin/rpm -qa --qf \"%{NAME}-%{VERSION}-%{RELEASE}-%{ARCH}\n\"") + + if self.isOptionEnabled("rpmva"): + self.runExe("/bin/rpm -Va") + return + diff --git a/src/lib/sos/plugins/samba.py b/src/lib/sos/plugins/samba.py new file mode 100644 index 00000000..848da265 --- /dev/null +++ b/src/lib/sos/plugins/samba.py @@ -0,0 +1,25 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class samba(sos.plugintools.PluginBase): + """This plugin gathers Samba related information + """ + def collect(self): + self.copyFileOrDir("/etc/samba") + self.runExe("/usr/bin/wbinfo -g") + self.runExe("/usr/bin/wbinfo -u") + return + diff --git a/src/lib/sos/plugins/selinux.py b/src/lib/sos/plugins/selinux.py new file mode 100644 index 00000000..51fe90d9 --- /dev/null +++ b/src/lib/sos/plugins/selinux.py @@ -0,0 +1,26 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class selinux(sos.plugintools.PluginBase): + """This plugin gathers selinux related information + """ + def collect(self): + self.runExe("/usr/bin/selinuxconfig") + self.runExe("/usr/sbin/sestatus") + self.runExe("/bin/rpm -q -V selinux-policy-targeted") + self.runExe("/bin/rpm -q -V selinux-policy-strict") + return + diff --git a/src/lib/sos/plugins/squid.py b/src/lib/sos/plugins/squid.py new file mode 100644 index 00000000..e552a99e --- /dev/null +++ b/src/lib/sos/plugins/squid.py @@ -0,0 +1,23 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class squid(sos.plugintools.PluginBase): + """This plugin gathers Squid related information + """ + def collect(self): + self.copyFileOrDir("/etc/squid/squid.conf") + return + diff --git a/src/lib/sos/plugins/startup.py b/src/lib/sos/plugins/startup.py new file mode 100644 index 00000000..820ee0e7 --- /dev/null +++ b/src/lib/sos/plugins/startup.py @@ -0,0 +1,26 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class startup(sos.plugintools.PluginBase): + """This plugin gathers startup information + """ + def collect(self): + self.copyFileOrDir("/etc/rc.d") + + self.runExe("/sbin/chkconfig --list") + # self.runExe("/bin/ls /etc/rc.d/rc*.d/") # This is redundant. + return + diff --git a/src/lib/sos/plugins/system.py b/src/lib/sos/plugins/system.py new file mode 100644 index 00000000..b98b40df --- /dev/null +++ b/src/lib/sos/plugins/system.py @@ -0,0 +1,31 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class system(sos.plugintools.PluginBase): + """This plugin gathers core system related information + """ + def collect(self): + self.copyFileOrDir("/proc/sys") + self.copyFileOrDir("/etc/sysctl.conf") + self.copyFileGlob("/etc/cron*") + self.copyFileOrDir("/etc/syslog.conf") + self.copyFileOrDir("/etc/ntp.conf") + self.copyFileOrDir("/etc/ntp/step-tickers") + self.copyFileOrDir("/etc/ntp/ntpservers") + self.copyFileOrDir("/etc/auto.*") + + return + diff --git a/src/lib/sos/plugins/tarball.py b/src/lib/sos/plugins/tarball.py new file mode 100644 index 00000000..787ffed2 --- /dev/null +++ b/src/lib/sos/plugins/tarball.py @@ -0,0 +1,41 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sys +import sos.plugintools +from sos.helpers import * + +class tarball(sos.plugintools.PluginBase): + """This plugin tars up the information gathered by sosreport + """ + def postproc(self, dstroot): + print "Please enter your first initial and last name (jsmith): ", + name = sys.stdin.readline()[:-1] + + print "Please enter the case number that you are generating this", + print "report for: ", + ticketNumber = sys.stdin.readline()[:-1] + + dirName = name + "." + ticketNumber + self.runExeInd("/bin/mkdir /tmp/%s" % dirName) + self.runExeInd("/bin/mv %s/* /tmp/%s" + % (dstroot, dirName)) + self.runExeInd("/bin/rm -rf %s" % dstroot) + self.runExeInd("/bin/tar --directory /tmp -jcf " + "/tmp/%s.tar.bz2 %s" + % (dirName, dirName)) + self.runExeInd("/bin/rm -rf /tmp/%s" % dirName) + print "Your tarball is located at /tmp/%s.tar.bz2" % dirName + return "/tmp/" + dirName + diff --git a/src/lib/sos/plugins/x11.py b/src/lib/sos/plugins/x11.py new file mode 100644 index 00000000..9d9b27c9 --- /dev/null +++ b/src/lib/sos/plugins/x11.py @@ -0,0 +1,26 @@ +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sos.plugintools + +class x11(sos.plugintools.PluginBase): + """This plugin gathers X related information + """ + def collect(self): + self.copyFileOrDir("/etc/X11") + self.copyFileGlob("/var/log/Xorg.*.log") + self.copyFileGlob("/var/log/XFree86.*.log") + self.runExe("/bin/dmesg | grep -e 'agpgart.'") + return + diff --git a/src/lib/sos/plugintools.py b/src/lib/sos/plugintools.py new file mode 100644 index 00000000..1a0fd9d4 --- /dev/null +++ b/src/lib/sos/plugintools.py @@ -0,0 +1,299 @@ +## plugintools.py +## This exports methods available for use by plugins for sos + +## Copyright (C) 2006 Steve Conklin <sconklin@redhat.com> + +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +from sos.helpers import * +import os, os.path, sys, string, itertools, glob + +class PluginBase: + """ + Base class for plugins + """ +# optionList = [] +# copiedFiles = [] +# copiedDirs = [] +# executedCommands = [] +# alerts = [] +# customText = "" +# cInfo = None +# piName = None +# optNames = [] +# optParms = [] + + def __init__(self, pluginname, commons): + try: + foo = len(self.optionList) + except: + self.optionList = [] + self.copiedFiles = [] + self.copiedDirs = [] + self.executedCommands = [] + self.alerts = [] + self.customText = "" + self.optNames = [] + self.optParms = [] + self.piName = pluginname + self.cInfo = commons + + # get the option list into a dictionary + for opt in self.optionList: + self.optNames.append(opt[0]) + self.optParms.append({'desc':opt[1], 'speed':opt[2], 'enabled':opt[3]}) + return + + + def __copyFile(self, src): + """ call cp to copy a file, collect return status and output. Returns the + destination file name. + """ + print "Copying %s" % src, + sys.stdout.flush() + + status, shout, sherr = sosGetCommandOutput("/bin/cp --parents " + src + " " + self.cInfo['dstroot']) + self.cInfo['logfd'].write(shout) + self.cInfo['logfd'].write(sherr) + sosStatus(status) + abspath = os.path.join(self.cInfo['dstroot'], src.lstrip(os.path.sep)) + relpath = sosRelPath(self.cInfo['rptdir'], abspath) + return relpath, abspath + + + def __copyDir(self, src): + """ call cp to copy a directory tree, collect return status and output. Returns the path where it + got put. + """ + print "Copying %s" % src, + sys.stdout.flush() + + status, shout, sherr = sosGetCommandOutput("/bin/cp --parents -R " + src + " " + self.cInfo['dstroot']) + self.cInfo['logfd'].write(shout) + self.cInfo['logfd'].write(sherr) + sosStatus(status) + abspath = self.cInfo['dstroot'] + src + relpath = sosRelPath(self.cInfo['rptdir'], abspath) + return relpath, abspath + + # Methods for dealing with options + + def getAllOptions(self): + return (self.optNames, self.optParms) + + def setOption(self, optionname, enable): + ''' enable or disable the named option. + ''' + for name, parms in zip(self.optNames, self.optParms): + if name == optionname: + parms['enabled'] = enable + + def isOptionEnabled(self, optionname): + ''' see whether the named option is enabled. + ''' + for name, parms in zip(self.optNames, self.optParms): + if name == optionname: + return parms['enabled'] + # nonexistent options aren't enabled. + return 0 + + def copyFileGlob(self, srcglob): + ''' Copy all files and/or directories specified by the glob to the + destination tree. + ''' + for source in glob.glob(srcglob): + self.copyFileOrDir(source) + + # Methods for copying files and shelling out + def copyFileOrDir(self, srcpath): + ''' Copy file or directory to the destination tree. If a directory, then everything + below it is recursively copied. A list of copied files are saved for use later + in preparing a report + ''' + if os.path.islink(srcpath): + # This is a symlink - We need to also copy the file that it points to + # file and dir symlinks ar ehandled the same + link = os.readlink(srcpath) + if os.path.isabs(link): + # the link was an absolute path, and will not point to the new + # tree. We must adjust it. + + # What's the name of the symlink on the dest tree? + dstslname = os.path.join(self.cInfo['dstroot'], srcpath.lstrip(os.path.sep)) + + # make sure the dst dir exists + if not (os.path.exists(os.path.dirname(dstslname)) and os.path.isdir(os.path.dirname(dstslname))): + # create the directory + os.makedirs(os.path.dirname(dstslname)) + + dstsldir = os.path.join(self.cInfo['dstroot'], link.lstrip(os.path.sep)) + # Create the symlink on the dst tree + rpth = sosRelPath(os.path.dirname(dstslname), dstsldir) + os.symlink(rpth, dstslname) + + if os.path.isdir(srcpath): + dstslname, abspath = self.__copyDir(srcpath) + self.copiedDirs.append({'srcpath':srcpath, 'dstpath':dstslname, 'symlink':"yes", 'pointsto':link}) + else: + dstslname, abspath = self.__copyFile(srcpath) + self.copiedFiles.append({'srcpath':srcpath, 'dstpath':dstslname, 'symlink':"yes", 'pointsto':link}) + + # Recurse to copy whatever it points to + newpath = os.path.normpath(os.path.join(os.path.dirname(srcpath), link)) + self.copyFileOrDir(newpath) + return abspath + + else: + if not os.path.exists(srcpath): + self.cInfo['logfd'].write("File or directory %s does not exist\n" % srcpath) + elif os.path.isdir(srcpath): + tdstpath, abspath = self.__copyDir(srcpath) + self.copiedDirs.append({'srcpath':srcpath, 'dstpath':tdstpath, 'symlink':"no", 'pointsto':""}) + return abspath + else: + # This is not a directory or a symlink + tdstpath, abspath = self.__copyFile(srcpath) + self.copiedFiles.append({'srcpath':srcpath, 'dstpath':tdstpath, 'symlink':"no"}) # save in our list + return abspath + + def runExeInd(self, exe): + """ Execute a command independantly of the output gathering part of + sosreport + """ + + # First check to make sure the binary exists and is runnable. + if not os.access(exe.split()[0], os.X_OK): + return + + status, shout, sherr = sosGetCommandOutput(exe) + + return status + + def runExe(self, exe): + """ Execute a command and save the output to a file for inclusion in + the report + """ + # First check to make sure the binary exists and is runnable. + if not os.access(exe.split()[0], os.X_OK): + return + + print "Collecting output from command <%s>" % (exe), + sys.stdout.flush() + + status, shout, sherr = sosGetCommandOutput(exe) + + # build file name for output + rawcmd = os.path.basename(exe).strip()[:28] + + # Mangle command to make it suitable for a file name + tabl = string.maketrans(" /\t;#$|%\"'`}{\n", "_._-----------") + mangledname = rawcmd.translate(tabl) + + outfn = self.cInfo['cmddir'] + "/" + self.piName + "." + mangledname + + # check for collisions + while os.path.exists(outfn): + outfn = outfn + "z" + + outfd = open(outfn, "w") + outfd.write(shout) + outfd.close() + self.cInfo['logfd'].write(sherr) + sosStatus(status) + # save info for later + self.executedCommands.append({'exe': exe, 'file':outfn}) # save in our list + return outfn + + # For adding output + def addAlert(self, alertstring): + """ Add an alert to the collection of alerts for this plugin. These + will be displayed in the report + """ + self.alerts.append(alertstring) + return + + + def addCustomText(self, text): + """ Append text to the custom text that is included in the report. This + is freeform and can include html. + """ + self.customText = self.customText + text + return + + + # What follows are the methods which may be overridden by the plugin + + + def collect(self): + pass + + def analyze(self): + pass + + def postproc(self, dstroot): + pass + + def report(self): + """ Present all information that was gathered in an html file that allows browsing + the results. + """ + # TODO make this prettier, this is a first pass + html = '<hr/><a name="%s"></a>\n' % self.piName + + # Intro + html = html + "<h2> Plugin <em>" + self.piName + "</em></h2>\n" + + # Files + if len(self.copiedFiles): + html = html + "<p>Files copied:<br><ul>\n" + for file in self.copiedFiles: + html = html + '<li><a href="%s">%s</a>' % (file['dstpath'], file['srcpath']) + if (file['symlink'] == "yes"): + html = html + " (symlink to %s)" % file['pointsto'] + html = html + '</li>\n' + html = html + "</ul></p>\n" + + # Dirs + if len(self.copiedDirs): + html = html + "<p>Directories Copied:<br><ul>\n" + for dir in self.copiedDirs: + html = html + '<li><a href="%s">%s</a>\n' % (dir['dstpath'], dir['srcpath']) + if (dir['symlink'] == "yes"): + html = html + " (symlink to %s)" % dir['pointsto'] + html = html + '</li>\n' + html = html + "</ul></p>\n" + + # Command Output + if len(self.executedCommands): + html = html + "<p>Commands Executed:<br><ul>\n" + for cmd in self.executedCommands: + html = html + '<li><a href="%s">%s</a></li>\n' % (cmd['file'], cmd['exe']) + html = html + "</ul></p>\n" + + # Alerts + if len(self.alerts): + html = html + "<p>Alerts:<br><ul>\n" + for alert in self.alerts: + html = html + '<li>%s</li>\n' % alert + html = html + "</ul></p>\n" + + # Custom Text + if (self.customText != ""): + html = html + "<p>Additional Information:<br>\n" + html = html + self.customText + "</p>\n" + + return html + + diff --git a/src/lib/sos/policyredhat.py b/src/lib/sos/policyredhat.py new file mode 100755 index 00000000..14e5fa8a --- /dev/null +++ b/src/lib/sos/policyredhat.py @@ -0,0 +1,70 @@ +## policy-redhat.py +## Implement policies required for the sos system support tool + +## Copyright (C) Steve Conklin <sconklin@redhat.com> + +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +#import os.path +#import copy +#import md5 +import os + +SOME_PATH = "/tmp/SomePath" + +#class SosError(Exception): +# def __init__(self, code, message): +# self.code = code +# self.message = message +# +# def __str__(self): +# return 'Sos Error %s: %s' % (self.code, self.message) + + +class SosPolicy: + "This class implements various policies for sos" + def __init__(self): + #print "Policy init" + return + + def validatePlugin(self, pluginpath): + "Validates the plugin as being acceptable to run" + # return value + # TODO implement this + #print "validating %s" % pluginpath + return True + + def allPkgsByName(self, name): + # FIXME: we're relying on rpm to sort the output list + cmd = "/bin/rpm --qf '%%{N}-%%{V}-%%{R}-%%{ARCH}\n' -q %s" % (name,) + pkgs = os.popen(cmd).readlines() + return [pkg[:-1] for pkg in pkgs if pkg.startswith(name)] + + def pkgByName(self, name): + # TODO: do a full NEVRA compare and return newest version, best arch + try: + # lame attempt at locating newest + pkg = self.allPkgsByName(name)[-1] + except IndexError: + pkg = None + + return pkg + + def pkgNVRA(self, pkg): + fields = pkg.split("-") + version, release, arch = fields[-3:] + name = "-".join(fields[:-3]) + return (name, version, release, arch) + diff --git a/src/setup.cfg b/src/setup.cfg new file mode 100644 index 00000000..5005a84b --- /dev/null +++ b/src/setup.cfg @@ -0,0 +1,12 @@ +# Example for setup.cfg +# You have to edit this file to reflect your system configuation + +[sdist] +template = MANIFEST.in + +[bdist_rpm] +provides = sos +requires = python >= 0:2.3 +release = 1 +packager = Steve Conklin <sconklin@redhat.com> +doc_files = README TODO diff --git a/src/setup.py b/src/setup.py new file mode 100644 index 00000000..c51a57b1 --- /dev/null +++ b/src/setup.py @@ -0,0 +1,27 @@ +""" +setup.py - Setup package with the help from Python's DistUtils +""" + +from distutils.core import setup +#from distutils.core import setup, Extension +from ConfigParser import ConfigParser +import sys,os,time + +# change release in spec file along with this version string +setup( + name = 'sos', + version = '0.1.6', + description = 'System Support Tools', + long_description = """Sos is a set of tools that gathers information about system + hardware and configuration. The information can then be used for + diagnostic purposes and debugging. Sos is commonly used to help + support technicians and developers.""", + author = 'Steve Conklin, et al.', + author_email = 'sconklin@redhat.com', + url = 'http://support.redhat.com/', + packages = ['sos', 'sos.plugins'], + scripts = [], + package_dir = {'': 'lib',}, + # data_files is broken for building dists, works for installs + data_files = [('/usr/sbin', ['sosreport'])] +) diff --git a/src/sos.spec b/src/sos.spec new file mode 100644 index 00000000..f79069b4 --- /dev/null +++ b/src/sos.spec @@ -0,0 +1,74 @@ +%{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} +%{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")} +%{!?python_siteinc: %define python_siteinc %(%{__python} -c "from distutils.sysconfig import get_python_inc; print get_python_inc()")} + +%define name sos +%define version 0.1 +# change release in setup.py and this file +%define release 6 + +Summary: System Support Tools +Name: %{name} +Version: %{version} +Release: %{release}%{?dist} +License: GPL +Group: Development/Libraries +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +BuildArch: noarch +Requires: python >= 0:2.3 +URL: http://www.redhat.com/support/ +# Using local source tarball until this can be released to public CVS system +Source0: %{name}-%{version}.tar.bz2 + +%description +SOS is a set of tools that gathers information about system +hardware and configuration. The information can then be used for +diagnostic purposes and debugging. Sos is commonly used to help +support technicians and developers. + + +%prep +%setup + +%build +python setup.py build + +%install +rm -rf ${RPM_BUILD_ROOT} +# The python setup.py does the same thing as the make install in other packages +%{__python} setup.py install --root=${RPM_BUILD_ROOT} + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root,-) +%{_sbindir}/sosreport +%dir %{python_sitelib}/sos/ +%{python_sitelib}/sos/plugins +%{python_sitelib}/sos/plugintools.py* +%{python_sitelib}/sos/__init__.py* +%{python_sitelib}/sos/helpers.py* +%{python_sitelib}/sos/policyredhat.py* +%doc README TODO + +%changelog +* Mon Jun 19 2006 Steve Conklin <sconklin at redhat dot com> - 0.1-6 +- Added LICENSE file containing GPL + +* Wed May 31 2006 Steve Conklin <sconklin at redhat dot com> - 0.1-5 +- Added fixes to network plugin and prepped for Fedora submission + +* Wed May 31 2006 John Berninger <jwb at redhat dot com> - 0.1-4 +- Reconsolidated subpackages into one package per discussion with sconklin + +* Mon May 22 2006 John Berninger <jwb at redhat dot com> - 0.1-3 +- Added ftp, ldap, mail, named, samba, squid SOS plugins +- Fixed various errors in kernel and hardware plugins + +* Mon May 22 2006 John Benringer <jwb at redhat dot com> - 0.1-2 +- split off cluster plugin into subpackage +- correct file payload lists + +* Mon May 22 2006 John Berninger <jwb at redhat dot com> - 0.1-1 +- initial package build diff --git a/src/sosreport b/src/sosreport new file mode 100755 index 00000000..5ebea18f --- /dev/null +++ b/src/sosreport @@ -0,0 +1,294 @@ +#!/usr/bin/env python + +## sosreport.py +## Implement policies required for the sos system support tool + +## Copyright (C) 2006 Steve Conklin <sconklin@redhat.com> + +### 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sys +import os +import curses +from optparse import OptionParser +import sos.policyredhat +from sos.helpers import * +from snack import * + +if os.getuid() != 0: + print 'You must run sosreport as root!' + sys.exit(1) + +# for debugging +raiseplugins = 1 + + +cmdParser=OptionParser() +cmdParser.add_option("-a","--alloptions",action="store_true",dest="alloptions",default=False,help="Use all options for loaded plugins") +cmdParser.add_option("-f","--fastoptions",action="store_true",dest="fastoptions",default=False,help="Use only fast options for loaded plugins") +cmdParser.add_option("-l","--list-plugins",action="store_true",dest="listPlugins",default=False,help="list existing plugins") +cmdParser.add_option("-n","--noplugin",action="append",dest="noplugins",help="list of plugin _not_ to load") + +(cmdLineOpts,cmdLineArgs)=cmdParser.parse_args() +#print cmdLineOpts + +def get_curse_options(alloptions): + #http://www.amk.ca/python/howto/curses/ + #http://gnosis.cx/publish/programming/charming_python_6.html + #http://www.wanware.com/tsgdocs/snack.html + # /usr/share/doc/newt-devel-0.51.6/ + # + + # allooptions is an array of (plug, plugname, optname, parms(dictionary)) tuples + plugName=[] + out=[] + + # get a sorted list of all plugin names + for p in alloptions: + if p[1] not in plugName: + plugName.append(p[1]) + + plugName.sort() + plugCbox=CheckboxTree(height=5,scroll=1) + + countOpt=-1 + + optDic={} + optDicCounter=0 + + # iterate over all plugins with options + for curPlugName in plugName: + plugCbox.addItem(curPlugName,(snackArgs['append'],)) + countOpt=countOpt+1 + + for opt in alloptions: + if opt[1] != curPlugName: + continue + + optName=opt[2] + enabled=opt[3]['enabled'] + speed=opt[3]['speed'] + optDesc=opt[3]['desc'] + + snt=optName+" ("+optDesc+") is "+speed + plugCbox.addItem(snt,(countOpt,snackArgs['append']),item=optDicCounter,selected=enabled) + optDic[optDicCounter]=opt + optDicCounter+=1 + + + screen = SnackScreen() + bb = ButtonBar(screen, (("Ok", "ok"), ("Cancel", "cancel"))) + g = GridForm(screen, "Select Sosreport Options", 1, 10) + g.add(plugCbox, 0, 0) + g.add(bb, 0, 1, growx = 1) + result = g.runOnce() + + screen.finish() + + for i in range(0, optDicCounter): + froo, wantit = plugCbox.getEntryValue(i) + optDic[i][3]['enabled'] = wantit + out.append((optDic[i])) + + return out + + +def sosreport(): + "This is the top-level function that gathers and processes all sosreport information" + loadedplugins = [] + alloptions = [] + + # TODO automatically locate the policy module?? + policy = sos.policyredhat.SosPolicy() + + # find the plugins path + paths = sys.path + for path in paths: + if path.strip()[-len("site-packages"):] == "site-packages": + pluginpath = path + "/sos/plugins" + + # TODO process command line to: + # load unsigned plugins + # disable one or more plugins + # set fast or slow collection without options menu presentation + + # Set up common info and create destinations + + dstroot = sosFindTmpDir() + os.chmod(dstroot, 0755) + cmddir = os.path.join(dstroot, "sos_commands") + logdir = os.path.join(dstroot, "sos_logs") + rptdir = os.path.join(dstroot, "sos_reports") + os.mkdir(cmddir, 0755) + os.mkdir(logdir, 0755) + os.mkdir(rptdir, 0755) + + # open log file + logfd = open(logdir + "/sos.log", "w") + + # set up dict so everyone can share the following + commons = {'dstroot': dstroot, 'cmddir': cmddir, 'logdir': logdir, 'rptdir': rptdir, 'logfd': logfd, 'policy': policy} + + + # validate and load plugins + plugins = os.listdir(pluginpath) + if cmdLineOpts.listPlugins: + for plug in plugins: + try: + if ((plug[-3:] == '.py') and (plug != "__init__.py")): + plugbase = plug[:-3] + pidot = "sos.plugins." + plugbase + print plugbase + except: + print "ouch" + sys.exit() + + for plug in plugins: + if ((plug[-3:] == '.py') and (plug != "__init__.py")): + try: + plugbase = plug[:-3] + pidot = "sos.plugins." + plugbase + #print "importing plugin: %s" % plugbase + try: + if policy.validatePlugin(pluginpath + plug): + PluginClass = importPlugin(pidot, plugbase) + else: + print "Plugin %s does not validate, skipping" % plug + continue + loadedplugins.append((plugbase, PluginClass(plugbase, commons))) + except: + print "Plugin %s does not install, skipping" % plug + raise + continue + except: + # TODO do better + if raiseplugins: + raise + print "plugin load failed for %s" % plug + + # Iterate over plugins for each stage + + # First, gather and process options + for plugname, plug in loadedplugins: + #print "processing options from plugin: %s" % plugname + try: + len(cmdLineOpts.noplugins) + if plugname not in cmdLineOpts.noplugins: + names, parms = plug.getAllOptions() + for optname, optparm in zip(names, parms): + alloptions.append((plug, plugname, optname, optparm)) + except: + names, parms = plug.getAllOptions() + for optname, optparm in zip(names, parms): + alloptions.append((plug, plugname, optname, optparm)) + + if not cmdLineOpts.fastoptions and not cmdLineOpts.alloptions: + cursedOptions=get_curse_options(alloptions) + elif cmdLineOpts.fastoptions: + for i in range(len(alloptions)): + for plug, plugname, optname, optparm in alloptions: + if optparm['speed']=='fast': + plug.setOption(optname,1) + elif cmdLineOpts.alloptions: + for i in range(len(alloptions)): + for plug, plugname, optname, optparm in alloptions: + plug.setOption(optname,1) + + # Call the collect method for each plugin + for plugname, plug in loadedplugins: + plug.collect() + + # Call the analyze method for each plugin + for plugname, plug in loadedplugins: + plug.analyze() + + # Sort the module names to do the report in alphabetical order + loadedplugins.sort() + + # Generate the header for the html output file + rfd = open(rptdir + "/" + "sosreport.html", "w") + rfd.write(""" + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> + <head> + <link rel="stylesheet" type="text/css" media="screen" href="donot.css" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>Sos System Report</title> + </head> + + <body> + """) + + rfd.write("Sosreport version blah blah<br />") + + + + + # Make a pass to gather Alerts and a list of module names + allAlerts = [] + plugNames = [] + for plugname, plug in loadedplugins: + for alert in plug.alerts: + # TODO include the plugin as a target of a link here + allAlerts.append('<a href="#%s">%s</a>: %s' % (plugname, plugname, alert)) + plugNames.append(plugname) + + + + # Create a table of links to the module info + rfd.write("<hr/><h3>Loaded Plugins:</h3>") + rfd.write("<table><tr>\n") + qq = 0 + rr = 0 + for i in range(len(plugNames)): + rfd.write('<td><a href="#%s">%s</a></td>\n' % (plugNames[i], plugNames[i])) + qq, rr = divmod(i,4) + if (rr == 3): + rfd.write('</tr>') + if not (rr == 3): + rfd.write('</tr>') + rfd.write('</table>\n') + + rfd.write('<hr/><h3>Alerts:</h3>') + rfd.write('<ul>') + for alert in allAlerts: + rfd.write('<li>%s</li>' % alert) + rfd.write('</ul>') + + + # Call the report method for each plugin + for plugname, plug in loadedplugins: + html = plug.report() + rfd.write(html) + + rfd.write("</body></html>") + + rfd.close() + + # Collect any needed user information (name, etc) + + # Clean up left over files, make tarball, whatever. + # Close all log files and perform any cleanup + logfd.close() + + # Call the postproc method for each plugin + for plugname, plug in loadedplugins: + root = plug.postproc(dstroot) + + if root == dstroot: + print "The report is in " + rptdir + "/" + "sosreport.html" + +if __name__ == '__main__': + sosreport() |