示例#1
0
 def _set_archive(self):
     if self.opts.compression_type not in ('auto', 'zip', 'bzip2', 'gzip', 'xz'):
         raise Exception("Invalid compression type specified. Options are: auto, zip, bzip2, gzip and xz")
     archive_name = os.path.join(self.opts.tmp_dir,self.policy.getArchiveName())
     if self.opts.compression_type == 'auto':
         auto_archive = self.policy.preferedArchive()
         self.archive = auto_archive(archive_name)
     elif self.opts.compression_type == 'zip':
         self.archive = ZipFileArchive(archive_name)
     else:
         self.archive = TarFileArchive(archive_name)
示例#2
0
class SoSReport(object):

    msg = _("""This utility will collect some detailed  information about the
hardware and setup of your %(distroa)s system.
The information is collected and an archive is  packaged under
/tmp, which you can send to a support representative.
%(distrob)s will use this information for diagnostic purposes ONLY
and it will be considered confidential information.

This process may take a while to complete.
No changes will be made to your system.

""" % {'distroa':__distro__, 'distrob':__distro__})

    def __init__(self, opts):
        self.loaded_plugins = deque()
        self.skipped_plugins = deque()
        self.all_options = deque()
        self.xml_report = XmlReport()

        try:
            import signal
            signal.signal(signal.SIGTERM, self.get_exit_handler())
        except Exception:
            pass # not available in java, but we don't care


        self.opts, self.args = parse_options(opts)
        self.tempfile_util = TempFileUtil(tmp_dir=self.opts.tmp_dir)
        self._set_debug()
        self._read_config()
        self.policy = sos.policies.load()
        self._is_root = self.policy.is_root()
        self._set_directories()
        self._setup_logging()
        self.policy.setCommons(self.get_commons())
        self.print_header()
        self.load_plugins()
        self._set_tunables()
        self._check_for_unknown_plugins()
        self._set_plugin_options()

    def print_header(self):
        self.ui_log.info("\n%s\n" % _("sosreport (version %s)" % (__version__,)))

    def get_commons(self):
        return {
                'cmddir': self.cmddir,
                'logdir': self.logdir,
                'rptdir': self.rptdir,
                'soslog': self.soslog,
                'policy': self.policy,
                'verbosity': self.opts.verbosity,
                'xmlreport': self.xml_report,
                'cmdlineopts': self.opts,
                'config': self.config
                }

    def get_temp_file(self):
        return self.tempfile_util.new()

    def _set_archive(self):
        if self.opts.compression_type not in ('auto', 'zip', 'bzip2', 'gzip', 'xz'):
            raise Exception("Invalid compression type specified. Options are: auto, zip, bzip2, gzip and xz")
        archive_name = os.path.join(self.opts.tmp_dir,self.policy.getArchiveName())
        if self.opts.compression_type == 'auto':
            auto_archive = self.policy.preferedArchive()
            self.archive = auto_archive(archive_name)
        elif self.opts.compression_type == 'zip':
            self.archive = ZipFileArchive(archive_name)
        else:
            self.archive = TarFileArchive(archive_name)

    def _set_directories(self):
        self.cmddir = 'sos_commands'
        self.logdir = 'sos_logs'
        self.rptdir = 'sos_reports'

    def _set_debug(self):
        if self.opts.debug:
            sys.excepthook = self._exception
            self.raise_plugins = True
        else:
            self.raise_plugins = False

    @staticmethod
    def _exception(etype, eval_, etrace):
        """ Wrap exception in debugger if not in tty """
        if hasattr(sys, 'ps1') or not sys.stderr.isatty():
            # we are in interactive mode or we don't have a tty-like
            # device, so we call the default hook
            sys.__excepthook__(etype, eval_, etrace)
        else:
            import traceback, pdb
            # we are NOT in interactive mode, print the exception...
            traceback.print_exception(etype, eval_, etrace, limit=2, file=sys.stdout)
            print
            # ...then start the debugger in post-mortem mode.
            pdb.pm()

    def _exit(self, error=0):
        raise SystemExit()
#        sys.exit(error)

    def _exit_nice(self):
        for plugname, plugin in self.loaded_plugins:
            plugin.exit_please()
        self.ui_log.info("All processes ended, cleaning up.")
        self._exit(1)

    def get_exit_handler(self):
        def exit_handler(signum, frame):
            self._exit_nice()
        return exit_handler

    def _read_config(self):
        self.config = ConfigParser.ConfigParser()
        if self.opts.config_file:
            config_file = self.opts.config_file
        else:
            config_file = '/etc/sos.conf'
        try:
            self.config.readfp(open(config_file))
        except IOError:
            pass

    def _setup_logging(self):

        if not sys.stdin.isatty():
            self.opts.nocolors = True
            self.opts.batch = True

        # main soslog
        self.soslog = logging.getLogger('sos')
        self.soslog.setLevel(logging.DEBUG)
        self.sos_log_file = self.get_temp_file()
        self.sos_log_file.close()
        flog = logging.FileHandler(self.sos_log_file.name)
        flog.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: %(message)s'))
        flog.setLevel(logging.INFO)
        self.soslog.addHandler(flog)

        if not self.opts.silent:
            console = logging.StreamHandler(sys.stderr)
            console.setFormatter(logging.Formatter('%(message)s'))
            if self.opts.verbosity > 1:
                console.setLevel(logging.DEBUG)
            elif self.opts.verbosity > 0:
                console.setLevel(logging.INFO)
            else:
                console.setLevel(logging.FATAL)
            self.soslog.addHandler(console)

        # ui log
        self.ui_log = logging.getLogger('sos.ui')
        self.ui_log.setLevel(logging.INFO)
        self.sos_ui_log_file = self.get_temp_file()
        self.sos_ui_log_file.close()
        ui_fhandler = logging.FileHandler(self.sos_ui_log_file.name)
        ui_fhandler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: %(message)s'))

        self.ui_log.addHandler(ui_fhandler)

        if not self.opts.silent:
            ui_console = logging.StreamHandler(sys.stdout)
            ui_console.setFormatter(logging.Formatter('%(message)s'))
            ui_console.setLevel(logging.INFO)
            self.ui_log.addHandler(ui_console)

        # profile logging
        if self.opts.profiler:
            self.proflog = logging.getLogger('sosprofile')
            self.proflog.setLevel(logging.DEBUG)
            self.sos_profile_log_file = self.get_temp_file()
            plog = logging.FileHandler(self.sos_profile_log_file.name)
            plog.setFormatter(logging.Formatter('%(message)s'))
            plog.setLevel(logging.DEBUG)
            self.proflog.addHandler(plog)

    def _finish_logging(self):
        logging.shutdown()

        # the logging module seems to persist in the jython/jboss/eap world
        # so the handlers need to be removed
        for logger in [logging.getLogger(x) for x in ('sos', 'sosprofile', 'sos.ui')]:
            for h in logger.handlers:
                logger.removeHandler(h)

        if getattr(self, "sos_log_file", None):
            self.archive.add_file(self.sos_log_file.name, dest=os.path.join('sos_logs', 'sos.log'))
        if getattr(self, "sos_profile_log_file", None):
            self.archive.add_file(self.sos_profile_log_file.name, dest=os.path.join('sos_logs', 'profile.log'))
        if getattr(self, "sos_ui_log_file", None):
            self.archive.add_file(self.sos_ui_log_file.name, dest=os.path.join('sos_logs', 'ui.log'))

    def _get_disabled_plugins(self):
        disabled = []
        if self.config.has_option("plugins", "disable"):
            disabled = [plugin.strip() for plugin in
                        self.config.get("plugins", "disable").split(',')]
        return disabled

    def _is_skipped(self, plugin_name):
        return (plugin_name in self.opts.noplugins or
                plugin_name in self._get_disabled_plugins())

    def _is_inactive(self, plugin_name, pluginClass):
        return (not pluginClass(self.get_commons()).checkenabled() and
                not plugin_name in self.opts.enableplugins  and
                not plugin_name in self.opts.onlyplugins)

    def _is_not_default(self, plugin_name, pluginClass):
        return (not pluginClass(self.get_commons()).defaultenabled() and
                not plugin_name in self.opts.enableplugins and
                not plugin_name in self.opts.onlyplugins)

    def _is_not_specified(self, plugin_name):
        return (self.opts.onlyplugins and
                not plugin_name in self.opts.onlyplugins)

    def _skip(self, plugin_class, reason="unknown"):
        self.skipped_plugins.append((
            plugin_class.name(),
            plugin_class(self.get_commons()),
            reason
        ))

    def _load(self, plugin_class):
        self.loaded_plugins.append((
            plugin_class.name(),
            plugin_class(self.get_commons())
        ))


    def load_plugins(self):

        helper = ImporterHelper(package_path=os.path.join('sos', 'plugins'))
        plugins = helper.get_modules()
        self.plugin_names = deque()

        # validate and load plugins
        for plug in plugins:
            plugbase, ext = os.path.splitext(plug)
            try:
                plugin_classes = import_plugin(plugbase)

                for plugin_class in plugin_classes:
                    if not self.policy.validatePlugin(plugin_class):
                        self.soslog.debug(_("plugin %s does not validate, skipping") % plug)
                        self._skip(plugin_class, "does not validate")
                        continue

                    if plugin_class.requires_root and not self._is_root:
                        self.soslog.debug(_("plugin %s requires root permissions to execute, skipping") % plug)
                        self._skip(plugin_class, "requires root")
                        continue

                    # plug-in is valid, let's decide whether run it or not
                    self.plugin_names.append(plugbase)

                    if any((self._is_skipped(plugbase),
                            self._is_inactive(plugbase, plugin_class),
                            self._is_not_default(plugbase, plugin_class),
                            self._is_not_specified(plugbase),
                            )):
                        self._skip(plugin_class, "inactive")
                        continue

                    self._load(plugin_class)
            except Exception, e:
                self.soslog.warning(_("plugin %s does not install, skipping: %s") % (plug, e))
                if self.raise_plugins:
                    raise
示例#3
0
 def setUp(self):
     self.tf = TarFileArchive('test')
示例#4
0
class TarFileArchiveTest(unittest.TestCase):

    def setUp(self):
        self.tf = TarFileArchive('test')

    def tearDown(self):
        os.unlink(self.tf.name())

    def check_for_file(self, filename):
        rtf = tarfile.open('test.tar')
        rtf.getmember(filename)
        rtf.close()

    def test_create(self):
        self.tf.close()
        self.assertTrue(os.path.exists('test.tar'))

    def test_add_file(self):
        self.tf.add_file('tests/ziptest')
        self.tf.close()

        self.check_for_file('test/tests/ziptest')

    def test_add_dir(self):
        self.tf.add_file('tests/')
        self.tf.close()

        self.check_for_file('test/tests/ziptest')

    def test_add_renamed(self):
        self.tf.add_file('tests/ziptest', dest='tests/ziptest_renamed')
        self.tf.close()

        self.check_for_file('test/tests/ziptest_renamed')

    def test_add_renamed_dir(self):
        self.tf.add_file('tests/', 'tests_renamed/')
        self.tf.close()

        self.check_for_file('test/tests_renamed/ziptest')

    def test_add_string(self):
        self.tf.add_string('this is content', 'tests/string_test.txt')
        self.tf.close()

        self.check_for_file('test/tests/string_test.txt')

    def test_get_file(self):
        self.tf.add_string('this is my content', 'tests/string_test.txt')

        afp = self.tf.open_file('tests/string_test.txt')
        self.assertEquals('this is my content', afp.read())

    def test_overwrite_file(self):
        self.tf.add_string('this is my content', 'tests/string_test.txt')
        self.tf.add_string('this is my new content', 'tests/string_test.txt')

        afp = self.tf.open_file('tests/string_test.txt')
        self.assertEquals('this is my new content', afp.read())

    def test_make_link(self):
        self.tf.add_file('tests/ziptest')
        self.tf.add_link('tests/ziptest', 'link_name')

        self.tf.close()
        self.check_for_file('test/link_name')

    def test_compress(self):
        name = self.tf.compress("gzip")
示例#5
0
 def setUp(self):
     self.tf = TarFileArchive('test')
示例#6
0
class TarFileArchiveTest(unittest.TestCase):
    def setUp(self):
        self.tf = TarFileArchive('test')

    def tearDown(self):
        os.unlink(self.tf.name())

    def check_for_file(self, filename):
        rtf = tarfile.open('test.tar')
        rtf.getmember(filename)
        rtf.close()

    def test_create(self):
        self.tf.close()
        self.assertTrue(os.path.exists('test.tar'))

    def test_add_file(self):
        self.tf.add_file('tests/ziptest')
        self.tf.close()

        self.check_for_file('test/tests/ziptest')

    def test_add_dir(self):
        self.tf.add_file('tests/')
        self.tf.close()

        self.check_for_file('test/tests/ziptest')

    def test_add_renamed(self):
        self.tf.add_file('tests/ziptest', dest='tests/ziptest_renamed')
        self.tf.close()

        self.check_for_file('test/tests/ziptest_renamed')

    def test_add_renamed_dir(self):
        self.tf.add_file('tests/', 'tests_renamed/')
        self.tf.close()

        self.check_for_file('test/tests_renamed/ziptest')

    def test_add_string(self):
        self.tf.add_string('this is content', 'tests/string_test.txt')
        self.tf.close()

        self.check_for_file('test/tests/string_test.txt')

    def test_get_file(self):
        self.tf.add_string('this is my content', 'tests/string_test.txt')

        afp = self.tf.open_file('tests/string_test.txt')
        self.assertEquals('this is my content', afp.read())

    def test_overwrite_file(self):
        self.tf.add_string('this is my content', 'tests/string_test.txt')
        self.tf.add_string('this is my new content', 'tests/string_test.txt')

        afp = self.tf.open_file('tests/string_test.txt')
        self.assertEquals('this is my new content', afp.read())

    def test_make_link(self):
        self.tf.add_file('tests/ziptest')
        self.tf.add_link('tests/ziptest', 'link_name')

        self.tf.close()
        self.check_for_file('test/link_name')

    def test_compress(self):
        name = self.tf.compress("gzip")
示例#7
0
 def setUp(self):
     self.tf = TarFileArchive("test")