diff --git a/oslo_concurrency/processutils.py b/oslo_concurrency/processutils.py index 436922a..b74e5f2 100644 --- a/oslo_concurrency/processutils.py +++ b/oslo_concurrency/processutils.py @@ -63,26 +63,33 @@ class UnknownArgumentError(Exception): class ProcessExecutionError(Exception): def __init__(self, stdout=None, stderr=None, exit_code=None, cmd=None, description=None): + super(ProcessExecutionError, self).__init__( + stdout, stderr, exit_code, cmd, description) self.exit_code = exit_code self.stderr = stderr self.stdout = stdout self.cmd = cmd self.description = description + def __str__(self): + description = self.description if description is None: description = _("Unexpected error while running command.") + + exit_code = self.exit_code if exit_code is None: exit_code = '-' + message = _('%(description)s\n' 'Command: %(cmd)s\n' 'Exit code: %(exit_code)s\n' 'Stdout: %(stdout)r\n' 'Stderr: %(stderr)r') % {'description': description, - 'cmd': cmd, + 'cmd': self.cmd, 'exit_code': exit_code, - 'stdout': stdout, - 'stderr': stderr} - super(ProcessExecutionError, self).__init__(message) + 'stdout': self.stdout, + 'stderr': self.stderr} + return message class NoRootWrapSpecified(Exception): diff --git a/oslo_concurrency/tests/unit/test_processutils.py b/oslo_concurrency/tests/unit/test_processutils.py index b868cb5..0fd8045 100644 --- a/oslo_concurrency/tests/unit/test_processutils.py +++ b/oslo_concurrency/tests/unit/test_processutils.py @@ -19,6 +19,7 @@ import errno import logging import multiprocessing import os +import pickle import resource import stat import subprocess @@ -467,6 +468,21 @@ grep foo def test_binary_undecodable_bytes_error(self): self.check_undecodable_bytes_error(True) + def test_picklable(self): + exc = processutils.ProcessExecutionError( + stdout='my stdout', stderr='my stderr', + exit_code=42, cmd='my cmd', + description='my description') + exc_message = str(exc) + + exc = pickle.loads(pickle.dumps(exc)) + self.assertEqual('my stdout', exc.stdout) + self.assertEqual('my stderr', exc.stderr) + self.assertEqual(42, exc.exit_code) + self.assertEqual('my cmd', exc.cmd) + self.assertEqual('my description', exc.description) + self.assertEqual(exc_message, str(exc)) + class ProcessExecutionErrorLoggingTest(test_base.BaseTestCase): def setUp(self):