Пример #1
0
    def test_stop_reactor_even_when_sync_exception_from_sysinfo_run(self):
        """
        Even when there's a synchronous exception from run_sysinfo, the reactor
        should be stopped.
        """
        self.log_helper.ignore_errors(ZeroDivisionError)
        reactor = FakeReactor()
        sysinfo = SysInfoPluginRegistry()
        sysinfo.run = lambda: 1 / 0
        d = run(["--sysinfo-plugins", "TestPlugin"], reactor=reactor,
                sysinfo=sysinfo)

        for x in reactor.queued_calls:
            x()

        self.assertEqual(reactor.scheduled_calls, [(0, reactor.stop, (), {})])
        return self.assertFailure(d, ZeroDivisionError)
Пример #2
0
    def test_output_is_only_displayed_once_deferred_fires(self):
        deferred = Deferred()

        # We mock the sysinfo.run() to return a Deferred but still
        # run the actual sysinfo.run() to gather the results from all
        # the plugins.  We cannot easily combine return_value and
        # side_effect because side_effect operates on the return_value,
        # thus firing the callback and writing sysinfo out to stdout.
        sysinfo = SysInfoPluginRegistry()
        original_sysinfo_run = sysinfo.run

        def wrapped_sysinfo_run(*args, **kwargs):
            original_sysinfo_run(*args, **kwargs)
            return deferred
        sysinfo.run = mock.Mock(side_effect=wrapped_sysinfo_run)

        run(["--sysinfo-plugins", "TestPlugin"], sysinfo=sysinfo)

        sysinfo.run.assert_called_once_with()

        self.assertNotIn("Test note", self.stdout.getvalue())
        deferred.callback(None)
        self.assertIn("Test note", self.stdout.getvalue())
Пример #3
0
class SysInfoPluginRegistryTest(HelperTestCase):
    def setUp(self):
        super(SysInfoPluginRegistryTest, self).setUp()
        self.sysinfo = SysInfoPluginRegistry()
        self.sysinfo_logfile = StringIO()
        self.handler = StreamHandler(self.sysinfo_logfile)
        self.logger = getLogger("landscape-sysinfo")
        self.logger.addHandler(self.handler)

    def tearDown(self):
        super(SysInfoPluginRegistryTest, self).tearDown()
        self.logger.removeHandler(self.handler)

    def test_is_plugin_registry(self):
        self.assertTrue(isinstance(self.sysinfo, PluginRegistry))

    def test_add_and_get_headers(self):
        self.sysinfo.add_header("Memory usage", "65%")
        self.sysinfo.add_header("Swap usage", "None")
        self.assertEqual(self.sysinfo.get_headers(), [("Memory usage", "65%"),
                                                      ("Swap usage", "None")])
        self.assertEqual(self.sysinfo.get_notes(), [])
        self.assertEqual(self.sysinfo.get_footnotes(), [])

    def test_add_same_header_twice(self):
        self.sysinfo.add_header("Header1", "Value1")
        self.sysinfo.add_header("Header2", "Value2")
        self.sysinfo.add_header("Header3", "Value3")
        self.sysinfo.add_header("Header2", "Value4")
        self.assertEqual(self.sysinfo.get_headers(), [("Header1", "Value1"),
                                                      ("Header2", "Value4"),
                                                      ("Header3", "Value3")])

    def test_add_header_with_none_value(self):
        self.sysinfo.add_header("Header1", "Value1")
        self.sysinfo.add_header("Header2", None)
        self.sysinfo.add_header("Header3", "Value3")
        self.assertEqual(self.sysinfo.get_headers(), [("Header1", "Value1"),
                                                      ("Header3", "Value3")])
        self.sysinfo.add_header("Header2", "Value2")
        self.assertEqual(self.sysinfo.get_headers(), [("Header1", "Value1"),
                                                      ("Header2", "Value2"),
                                                      ("Header3", "Value3")])

    def test_add_and_get_notes(self):
        self.sysinfo.add_note("Your laptop is burning!")
        self.sysinfo.add_note("Oh, your house too, btw.")
        self.assertEqual(
            self.sysinfo.get_notes(),
            ["Your laptop is burning!", "Oh, your house too, btw."])
        self.assertEqual(self.sysinfo.get_headers(), [])
        self.assertEqual(self.sysinfo.get_footnotes(), [])

    def test_add_and_get_footnotes(self):
        self.sysinfo.add_footnote("Graphs available at http://graph")
        self.sysinfo.add_footnote("Go! Go!")
        self.assertEqual(self.sysinfo.get_footnotes(),
                         ["Graphs available at http://graph", "Go! Go!"])
        self.assertEqual(self.sysinfo.get_headers(), [])
        self.assertEqual(self.sysinfo.get_notes(), [])

    def test_run(self):
        class Plugin(object):
            def __init__(self, deferred):
                self._deferred = deferred

            def register(self, registry):
                pass

            def run(self):
                return self._deferred

        plugin_deferred1 = Deferred()
        plugin_deferred2 = Deferred()

        plugin1 = Plugin(plugin_deferred1)
        plugin2 = Plugin(plugin_deferred2)

        self.sysinfo.add(plugin1)
        self.sysinfo.add(plugin2)

        def check_result(result):
            self.assertEqual(result, [123, 456])

        deferred = self.sysinfo.run()
        deferred.addBoth(check_result)

        self.assertEqual(deferred.called, False)
        plugin_deferred1.callback(123)
        self.assertEqual(deferred.called, False)
        plugin_deferred2.callback(456)
        self.assertEqual(deferred.called, True)

    plugin_exception_message = (
        "There were exceptions while processing one or more plugins. "
        "See %s/sysinfo.log for more information.")

    def test_plugins_run_after_synchronous_error(self):
        """
        Even when a plugin raises a synchronous error, other plugins will
        continue to be run.
        """
        self.log_helper.ignore_errors(ZeroDivisionError)
        plugins_what_run = []

        class BadPlugin(object):
            def register(self, registry):
                pass

            def run(self):
                plugins_what_run.append(self)
                1 / 0

        class GoodPlugin(object):
            def register(self, registry):
                pass

            def run(self):
                plugins_what_run.append(self)
                return succeed(None)

        plugin1 = BadPlugin()
        plugin2 = GoodPlugin()
        self.sysinfo.add(plugin1)
        self.sysinfo.add(plugin2)
        self.sysinfo.run()
        self.assertEqual(plugins_what_run, [plugin1, plugin2])
        log = self.sysinfo_logfile.getvalue()
        message = "BadPlugin plugin raised an exception."
        self.assertIn(message, log)
        self.assertIn("1 / 0", log)
        self.assertIn("ZeroDivisionError", log)

        path = os.path.expanduser("~/.landscape")
        self.assertEqual(self.sysinfo.get_notes(),
                         [self.plugin_exception_message % path])

    def test_asynchronous_errors_logged(self):
        self.log_helper.ignore_errors(ZeroDivisionError)

        class BadPlugin(object):
            def register(self, registry):
                pass

            def run(self):
                return fail(ZeroDivisionError("yay"))

        plugin = BadPlugin()
        self.sysinfo.add(plugin)
        self.sysinfo.run()
        log = self.sysinfo_logfile.getvalue()
        message = "BadPlugin plugin raised an exception."
        self.assertIn(message, log)
        self.assertIn("ZeroDivisionError: yay", log)
        path = os.path.expanduser("~/.landscape")
        self.assertEqual(self.sysinfo.get_notes(),
                         [self.plugin_exception_message % path])

    def test_multiple_exceptions_get_one_note(self):
        self.log_helper.ignore_errors(ZeroDivisionError)

        class RegularBadPlugin(object):
            def register(self, registry):
                pass

            def run(self):
                1 / 0

        class AsyncBadPlugin(object):
            def register(self, registry):
                pass

            def run(self):
                return fail(ZeroDivisionError("Hi"))

        plugin1 = RegularBadPlugin()
        plugin2 = AsyncBadPlugin()
        self.sysinfo.add(plugin1)
        self.sysinfo.add(plugin2)
        self.sysinfo.run()

        path = os.path.expanduser("~/.landscape")
        self.assertEqual(self.sysinfo.get_notes(),
                         [self.plugin_exception_message % path])

    @mock.patch("os.getuid", return_value=0)
    def test_exception_running_as_privileged_user(self, uid_mock):
        """
        If a Plugin fails while running and the sysinfo binary is running with
        a uid of 0, Landscape sysinfo should write to the system logs
        directory.
        """
        class AsyncBadPlugin(object):
            def register(self, registry):
                pass

            def run(self):
                return fail(ZeroDivisionError("Hi"))

        self.log_helper.ignore_errors(ZeroDivisionError)

        plugin = AsyncBadPlugin()
        self.sysinfo.add(plugin)
        self.sysinfo.run()
        uid_mock.assert_called_with()

        path = "/var/log/landscape"
        self.assertEqual(self.sysinfo.get_notes(),
                         [self.plugin_exception_message % path])