error.py revision 9167225694a0c89a256172a189e153fe4e4c82f7
1"""
2Internal global error types
3"""
4
5import sys, traceback
6from traceback import format_exception
7
8# Add names you want to be imported by 'from errors import *' to this list.
9# This must be list not a tuple as we modify it to include all of our
10# the Exception classes we define below at the end of this file.
11__all__ = ['format_error']
12
13
14def format_error():
15    t, o, tb = sys.exc_info()
16    trace = format_exception(t, o, tb)
17    # Clear the backtrace to prevent a circular reference
18    # in the heap -- as per tutorial
19    tb = ''
20
21    return ''.join(trace)
22
23class JobContinue(SystemExit):
24    """Allow us to bail out requesting continuance."""
25    pass
26
27
28class JobComplete(SystemExit):
29    """Allow us to bail out indicating continuation not required."""
30    pass
31
32
33class AutotestError(Exception):
34    """The parent of all errors deliberatly thrown within the client code."""
35    pass
36
37
38class JobError(AutotestError):
39    """Indicates an error which terminates and fails the whole job."""
40    pass
41
42
43class TestBaseException(AutotestError):
44    """The parent of all test exceptions."""
45    pass
46
47
48class TestError(TestBaseException):
49    """Indicates that something went wrong with the test harness itself."""
50    exit_status="ERROR"
51    pass
52
53
54class TestNAError(TestBaseException):
55    """Indictates that the test is Not Applicable.  Should be thrown
56    when various conditions are such that the test is inappropriate."""
57    exit_status="TEST_NA"
58    pass
59
60
61class TestFail(TestBaseException):
62    """Indicates that the test failed, but the job will not continue."""
63    exit_status="FAIL"
64    pass
65
66
67class TestWarn(TestBaseException):
68    """Indicates that bad things (may) have happened, but not an explicit
69    failure."""
70    exit_status="WARN"
71    pass
72
73
74class UnhandledTestError(TestError):
75    """Indicates an unhandled error in a test."""
76    def __init__(self, unhandled_exception):
77        if isinstance(unhandled_exception, TestError):
78            TestError.__init__(self, *unhandled_exception.args)
79        else:
80            msg = "Unhandled %s: %s"
81            msg %= (unhandled_exception.__class__.__name__,
82                    unhandled_exception)
83            msg += "\n" + traceback.format_exc()
84            TestError.__init__(self, msg)
85
86
87class UnhandledTestFail(TestFail):
88    """Indicates an unhandled fail in a test."""
89    def __init__(self, unhandled_exception):
90        if isinstance(unhandled_exception, TestFail):
91            TestFail.__init__(self, *unhandled_exception.args)
92        else:
93            msg = "Unhandled %s: %s"
94            msg %= (unhandled_exception.__class__.__name__,
95                    unhandled_exception)
96            msg += "\n" + traceback.format_exc()
97            TestFail.__init__(self, msg)
98
99
100class CmdError(TestError):
101    """\
102    Indicates that a command failed, is fatal to the test unless caught.
103    """
104    def __init__(self, command, result_obj, additional_text=None):
105        TestError.__init__(self, command, result_obj, additional_text)
106        self.command = command
107        self.result_obj = result_obj
108        self.additional_text = additional_text
109
110
111    def __str__(self):
112        if self.result_obj.exit_status is None:
113            msg = "Command <%s> failed and is not responding to signals"
114            msg %= self.command
115        else:
116            msg = "Command <%s> failed, rc=%d"
117            msg %= (self.command, self.result_obj.exit_status)
118
119        if self.additional_text:
120            msg += ", " + self.additional_text
121        msg += '\n' + repr(self.result_obj)
122        return msg
123
124
125class PackageError(TestError):
126    """Indicates an error trying to perform a package operation."""
127    pass
128
129
130class BarrierError(JobError):
131    """Indicates an error happened during a barrier operation."""
132    pass
133
134
135class InstallError(JobError):
136    """Indicates an installation error which Terminates and fails the job."""
137    pass
138
139
140class AutotestRunError(AutotestError):
141    pass
142
143
144class AutotestTimeoutError(AutotestError):
145    """This exception is raised when an autotest test exceeds the timeout
146    parameter passed to run_timed_test and is killed.
147    """
148
149
150# server-specific errors
151
152class AutoservError(Exception):
153    pass
154
155
156class AutoservSSHTimeout(AutoservError):
157    """SSH experienced a connection timeout"""
158    pass
159
160
161class AutoservRunError(AutoservError):
162    """\
163    Errors raised by one of the run functions.  Should always be
164    constructed with a tuple of two args (error description (str),
165    run result object).
166    """
167    def __init__(self, description, result_obj):
168        self.description = description
169        self.result_obj = result_obj
170        AutoservError.__init__(self, description, result_obj)
171
172    def __str__(self):
173        return self.description + '\n' + repr(self.result_obj)
174
175
176class AutoservVirtError(AutoservError):
177    """Vitualization related error"""
178    pass
179
180
181class AutoservUnsupportedError(AutoservError):
182    """Error raised when you try to use an unsupported optional feature"""
183    pass
184
185
186class AutoservHostError(AutoservError):
187    """Error reaching a host"""
188    pass
189
190
191class AutoservRebootError(AutoservError):
192    """Error occured while rebooting a machine"""
193    pass
194
195
196class AutoservSubcommandError(AutoservError):
197    """Indicates an error while executing a (forked) subcommand"""
198    def __init__(self, func, exit_code):
199        AutoservError.__init__(self, func, exit_code)
200        self.func = func
201        self.exit_code = exit_code
202
203    def __str__(self):
204        return ("Subcommand %s failed with exit code %d" %
205                (self.func, self.exit_code))
206
207
208# This MUST remain at the end of the file.
209# Limit 'from error import *' to only import the exception instances.
210for _name, _thing in locals().items():
211    try:
212        if issubclass(_thing, Exception):
213            __all__.append(_name)
214    except TypeError:
215        pass  # _thing not a class
216__all__ = tuple(__all__)
217