diff --git a/nova/cmd/manage.py b/nova/cmd/manage.py index 3954a2594b03..d36eb496edc0 100644 --- a/nova/cmd/manage.py +++ b/nova/cmd/manage.py @@ -1565,10 +1565,14 @@ category_opt = cfg.SubCommandOpt('category', help='Available categories', handler=add_command_parsers) +post_mortem_opt = cfg.BoolOpt('post-mortem', + default=False, + help='Allow post-mortem debugging') + def main(): """Parse options and call the appropriate class/method.""" - CONF.register_cli_opt(category_opt) + CONF.register_cli_opts([category_opt, post_mortem_opt]) config.parse_args(sys.argv) logging.set_defaults( default_log_levels=logging.get_default_log_levels() + @@ -1590,5 +1594,9 @@ def main(): rpc.cleanup() return(ret) except Exception: - print(_("An error has occurred:\n%s") % traceback.format_exc()) + if CONF.post_mortem: + import pdb + pdb.post_mortem() + else: + print(_("An error has occurred:\n%s") % traceback.format_exc()) return(1) diff --git a/nova/tests/unit/test_nova_manage.py b/nova/tests/unit/test_nova_manage.py index a6f6cd83f559..81a05530b2af 100644 --- a/nova/tests/unit/test_nova_manage.py +++ b/nova/tests/unit/test_nova_manage.py @@ -1578,9 +1578,20 @@ class TestNovaManageMain(test.NoDBTestCase): def test_error_traceback(self, mock_conf, mock_parse_args): with mock.patch.object(manage.cmd_common, 'get_action_fn', side_effect=test.TestingException('oops')): + mock_conf.post_mortem = False self.assertEqual(1, manage.main()) # assert the traceback is dumped to stdout output = self.output.getvalue() self.assertIn('An error has occurred', output) self.assertIn('Traceback', output) self.assertIn('oops', output) + + @mock.patch('pdb.post_mortem') + @mock.patch.object(manage.config, 'parse_args') + @mock.patch.object(manage, 'CONF') + def test_error_post_mortem(self, mock_conf, mock_parse_args, mock_pm): + with mock.patch.object(manage.cmd_common, 'get_action_fn', + side_effect=test.TestingException('oops')): + mock_conf.post_mortem = True + self.assertEqual(1, manage.main()) + self.assertTrue(mock_pm.called)