aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ChangeLog155
-rw-r--r--src/LICENSE340
-rw-r--r--src/MANIFEST.in4
-rw-r--r--src/Makefile46
-rw-r--r--src/README15
-rw-r--r--src/TODO25
-rwxr-xr-xsrc/example_plugins/example.py108
-rw-r--r--src/example_plugins/fsusage.py23
-rw-r--r--src/example_plugins/release.py23
-rwxr-xr-xsrc/example_plugins/runcommand.py60
-rwxr-xr-xsrc/example_plugins/template.py104
-rw-r--r--src/lib/sos/__init__.py0
-rwxr-xr-xsrc/lib/sos/helpers.py140
-rw-r--r--src/lib/sos/plugins/__init__.py0
-rw-r--r--src/lib/sos/plugins/apache.py24
-rw-r--r--src/lib/sos/plugins/bootloader.py31
-rw-r--r--src/lib/sos/plugins/cluster.py25
-rw-r--r--src/lib/sos/plugins/filesys.py46
-rw-r--r--src/lib/sos/plugins/ftp.py24
-rw-r--r--src/lib/sos/plugins/general.py35
-rw-r--r--src/lib/sos/plugins/hardware.py50
-rw-r--r--src/lib/sos/plugins/kernel.py61
-rw-r--r--src/lib/sos/plugins/ldap.py24
-rw-r--r--src/lib/sos/plugins/libraries.py24
-rw-r--r--src/lib/sos/plugins/mail.py25
-rw-r--r--src/lib/sos/plugins/memory.py27
-rw-r--r--src/lib/sos/plugins/named.py34
-rw-r--r--src/lib/sos/plugins/networking.py58
-rw-r--r--src/lib/sos/plugins/pam.py23
-rw-r--r--src/lib/sos/plugins/process.py24
-rw-r--r--src/lib/sos/plugins/rhn.py86
-rw-r--r--src/lib/sos/plugins/rpm.py32
-rw-r--r--src/lib/sos/plugins/samba.py25
-rw-r--r--src/lib/sos/plugins/selinux.py26
-rw-r--r--src/lib/sos/plugins/squid.py23
-rw-r--r--src/lib/sos/plugins/startup.py26
-rw-r--r--src/lib/sos/plugins/system.py31
-rw-r--r--src/lib/sos/plugins/tarball.py41
-rw-r--r--src/lib/sos/plugins/x11.py26
-rw-r--r--src/lib/sos/plugintools.py299
-rwxr-xr-xsrc/lib/sos/policyredhat.py70
-rw-r--r--src/setup.cfg12
-rw-r--r--src/setup.py27
-rw-r--r--src/sos.spec74
-rwxr-xr-xsrc/sosreport294
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()