• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#pylint: disable-msg=C0111
2
3"""
4Internal global error types
5"""
6
7import sys, traceback
8from traceback import format_exception
9
10# Add names you want to be imported by 'from errors import *' to this list.
11# This must be list not a tuple as we modify it to include all of our
12# the Exception classes we define below at the end of this file.
13__all__ = ['format_error']
14
15
16def format_error():
17    t, o, tb = sys.exc_info()
18    trace = format_exception(t, o, tb)
19    # Clear the backtrace to prevent a circular reference
20    # in the heap -- as per tutorial
21    tb = ''
22
23    return ''.join(trace)
24
25
26class TimeoutException(Exception):
27    """Generic exception raised on retry timeouts."""
28
29
30class JobContinue(SystemExit):
31    """Allow us to bail out requesting continuance."""
32
33
34class JobComplete(SystemExit):
35    """Allow us to bail out indicating continuation not required."""
36
37
38class AutotestError(Exception):
39    """The parent of all errors deliberatly thrown within the client code."""
40
41
42class JobError(AutotestError):
43    """Indicates an error which terminates and fails the whole job (ABORT)."""
44
45
46class UnhandledJobError(JobError):
47    """Indicates an unhandled error in a job."""
48    def __init__(self, unhandled_exception):
49        if isinstance(unhandled_exception, JobError):
50            JobError.__init__(self, *unhandled_exception.args)
51        elif isinstance(unhandled_exception, basestring):
52            JobError.__init__(self, unhandled_exception)
53        else:
54            msg = "Unhandled %s: %s"
55            msg %= (unhandled_exception.__class__.__name__,
56                    unhandled_exception)
57            msg += "\n" + traceback.format_exc()
58            JobError.__init__(self, msg)
59
60
61class TestBaseException(AutotestError):
62    """The parent of all test exceptions."""
63    # Children are required to override this.  Never instantiate directly.
64    exit_status = "NEVER_RAISE_THIS"
65
66
67class TestError(TestBaseException):
68    """Indicates that something went wrong with the test harness itself."""
69    exit_status = "ERROR"
70
71
72class TestNAError(TestBaseException):
73    """Indictates that the test is Not Applicable.  Should be thrown
74    when various conditions are such that the test is inappropriate."""
75    exit_status = "TEST_NA"
76
77
78class TestFail(TestBaseException):
79    """Indicates that the test failed, but the job will not continue."""
80    exit_status = "FAIL"
81
82
83class TestWarn(TestBaseException):
84    """Indicates that bad things (may) have happened, but not an explicit
85    failure."""
86    exit_status = "WARN"
87
88
89class TestFailRetry(TestFail):
90    """Indicates that the test failed, but in a manner that may be retried
91    if test retries are enabled for this test."""
92    exit_status = "FAIL"
93
94
95class UnhandledTestError(TestError):
96    """Indicates an unhandled error in a test."""
97    def __init__(self, unhandled_exception):
98        if isinstance(unhandled_exception, TestError):
99            TestError.__init__(self, *unhandled_exception.args)
100        elif isinstance(unhandled_exception, basestring):
101            TestError.__init__(self, unhandled_exception)
102        else:
103            msg = "Unhandled %s: %s"
104            msg %= (unhandled_exception.__class__.__name__,
105                    unhandled_exception)
106            msg += "\n" + traceback.format_exc()
107            TestError.__init__(self, msg)
108
109
110class UnhandledTestFail(TestFail):
111    """Indicates an unhandled fail in a test."""
112    def __init__(self, unhandled_exception):
113        if isinstance(unhandled_exception, TestFail):
114            TestFail.__init__(self, *unhandled_exception.args)
115        elif isinstance(unhandled_exception, basestring):
116            TestFail.__init__(self, unhandled_exception)
117        else:
118            msg = "Unhandled %s: %s"
119            msg %= (unhandled_exception.__class__.__name__,
120                    unhandled_exception)
121            msg += "\n" + traceback.format_exc()
122            TestFail.__init__(self, msg)
123
124
125class CmdError(TestError):
126    """Indicates that a command failed, is fatal to the test unless caught."""
127    def __init__(self, command, result_obj, additional_text=None):
128        TestError.__init__(self, command, result_obj, additional_text)
129        self.command = command
130        self.result_obj = result_obj
131        self.additional_text = additional_text
132
133    def __str__(self):
134        if self.result_obj.exit_status is None:
135            msg = "Command <%s> failed and is not responding to signals"
136            msg %= self.command
137        else:
138            msg = "Command <%s> failed, rc=%d"
139            msg %= (self.command, self.result_obj.exit_status)
140
141        if self.additional_text:
142            msg += ", " + self.additional_text
143        msg += '\n' + repr(self.result_obj)
144        return msg
145
146    def __eq__(self, other):
147        if type(self) == type(other):
148            return (self.command == other.command
149                    and self.result_obj == other.result_obj
150                    and self.additional_text == other.additional_text)
151        else:
152            return NotImplemented
153
154
155class CmdTimeoutError(CmdError):
156    """Indicates that a command timed out."""
157
158
159class PackageError(TestError):
160    """Indicates an error trying to perform a package operation."""
161
162
163class BarrierError(JobError):
164    """Indicates an error happened during a barrier operation."""
165
166
167class BarrierAbortError(BarrierError):
168    """Indicate that the barrier was explicitly aborted by a member."""
169
170
171class InstallError(JobError):
172    """Indicates an installation error which Terminates and fails the job."""
173
174
175class AutotestRunError(AutotestError):
176    """Indicates a problem running server side control files."""
177
178
179class AutotestTimeoutError(AutotestError):
180    """This exception is raised when an autotest test exceeds the timeout
181    parameter passed to run_timed_test and is killed.
182    """
183
184
185class GenericHostRunError(Exception):
186    """Indicates a problem in the host run() function running in either client
187    or server code.
188
189    Should always be constructed with a tuple of two args (error description
190    (str), run result object). This is a common class used to create the client
191    and server side versions of it when the distinction is useful.
192    """
193    def __init__(self, description, result_obj):
194        self.description = description
195        self.result_obj = result_obj
196        Exception.__init__(self, description, result_obj)
197
198    def __str__(self):
199        return self.description + '\n' + repr(self.result_obj)
200
201
202class HostInstallTimeoutError(JobError):
203    """
204    Indicates the machine failed to be installed after the predetermined
205    timeout.
206    """
207
208
209class AutotestHostRunError(GenericHostRunError, AutotestError):
210    pass
211
212
213class AutotestHostRunCmdError(AutotestHostRunError):
214    """Indicates that the command run via Host.run failed.
215
216    This is equivalent to CmdError when raised from a Host object instead of
217    directly on the DUT using utils.run
218    """
219
220    def __init__(self, command, result_obj, additional_text=''):
221        description = command
222        if additional_text:
223            description += ' (%s)' % additional_text
224        super(AutotestHostRunCmdError, self).__init__(description, result_obj)
225        self.command = command
226        self.additional_text = additional_text
227
228
229class AutotestHostRunTimeoutError(AutotestHostRunCmdError):
230    """Indicates that a command run via Host.run timed out.
231
232    This is equivalent to CmdTimeoutError when raised from a Host object instead
233    of directly on the DUT using utils.run
234    """
235
236
237# server-specific errors
238
239class AutoservError(Exception):
240    pass
241
242
243class AutoservSSHTimeout(AutoservError):
244    """SSH experienced a connection timeout"""
245
246
247class AutoservRunError(GenericHostRunError, AutoservError):
248    pass
249
250
251class AutoservSshPermissionDeniedError(AutoservRunError):
252    """Indicates that a SSH permission denied error was encountered."""
253
254
255class AutoservUnsupportedError(AutoservError):
256    """Error raised when you try to use an unsupported optional feature"""
257
258
259class AutoservHostError(AutoservError):
260    """Error reaching a host"""
261
262
263class AutoservHostIsShuttingDownError(AutoservHostError):
264    """Host is shutting down"""
265
266
267class AutoservNotMountedHostError(AutoservHostError):
268    """Found unmounted partitions that should be mounted"""
269
270
271class AutoservSshPingHostError(AutoservHostError):
272    """SSH ping failed"""
273
274
275class AutoservDiskFullHostError(AutoservHostError):
276    """Not enough free disk space on host"""
277
278    def __init__(self, path, want_gb, free_space_gb):
279        super(AutoservDiskFullHostError, self).__init__(
280            'Not enough free space on %s - %.3fGB free, want %.3fGB' %
281                    (path, free_space_gb, want_gb))
282        self.path = path
283        self.want_gb = want_gb
284        self.free_space_gb = free_space_gb
285
286
287class AutoservNoFreeInodesError(AutoservHostError):
288    """Not enough free i-nodes on host"""
289
290    def __init__(self, path, want_inodes, free_inodes):
291        super(AutoservNoFreeInodesError, self).__init__(
292            'Not enough free inodes on %s - %d free, want %d' %
293                    (path, free_inodes, want_inodes))
294        self.path = path
295        self.want_inodes = want_inodes
296        self.free_inodes = free_inodes
297
298
299class AutoservHardwareHostError(AutoservHostError):
300    """Found hardware problems with the host"""
301
302
303class AutoservRebootError(AutoservError):
304    """Error occured while rebooting a machine"""
305
306
307class AutoservShutdownError(AutoservRebootError):
308    """Error occured during shutdown of machine"""
309
310
311class AutoservSuspendError(AutoservRebootError):
312    """Error occured while suspending a machine"""
313
314
315class AutoservSubcommandError(AutoservError):
316    """Indicates an error while executing a (forked) subcommand"""
317    def __init__(self, func, exit_code):
318        AutoservError.__init__(self, func, exit_code)
319        self.func = func
320        self.exit_code = exit_code
321
322    def __str__(self):
323        return ("Subcommand %s failed with exit code %d" %
324                (self.func, self.exit_code))
325
326
327class AutoservRepairTotalFailure(AutoservError):
328    """Raised if all attempts to repair the DUT failed."""
329
330
331class AutoservInstallError(AutoservError):
332    """Error occured while installing autotest on a host"""
333
334
335class AutoservPidAlreadyDeadError(AutoservError):
336    """Error occured by trying to kill a nonexistant PID"""
337
338
339# packaging system errors
340
341class PackagingError(AutotestError):
342    'Abstract error class for all packaging related errors.'
343
344
345class PackageUploadError(PackagingError):
346    'Raised when there is an error uploading the package'
347
348
349class PackageFetchError(PackagingError):
350    'Raised when there is an error fetching the package'
351
352
353class PackageRemoveError(PackagingError):
354    'Raised when there is an error removing the package'
355
356
357class PackageInstallError(PackagingError):
358    'Raised when there is an error installing the package'
359
360
361class RepoDiskFullError(PackagingError):
362    'Raised when the destination for packages is full'
363
364
365class RepoWriteError(PackagingError):
366    "Raised when packager cannot write to a repo's desitnation"
367
368
369class RepoUnknownError(PackagingError):
370    "Raised when packager cannot write to a repo's desitnation"
371
372
373class RepoError(PackagingError):
374    "Raised when a repo isn't working in some way"
375
376
377class StageControlFileFailure(Exception):
378    """Exceptions encountered staging control files."""
379
380
381class CrosDynamicSuiteException(Exception):
382    """
383    Base class for exceptions coming from dynamic suite code in
384    server/cros/dynamic_suite/*.
385    """
386
387
388class StageBuildFailure(CrosDynamicSuiteException):
389    """Raised when the dev server throws 500 while staging a build."""
390
391
392class ControlFileEmpty(CrosDynamicSuiteException):
393    """Raised when the control file exists on the server, but can't be read."""
394
395
396class ControlFileMalformed(CrosDynamicSuiteException):
397    """Raised when an invalid control file is read."""
398
399
400class AsynchronousBuildFailure(CrosDynamicSuiteException):
401    """Raised when the dev server throws 500 while finishing staging of a build.
402    """
403
404
405class SuiteArgumentException(CrosDynamicSuiteException):
406    """Raised when improper arguments are used to run a suite."""
407
408
409class MalformedDependenciesException(CrosDynamicSuiteException):
410    """Raised when a build has a malformed dependency_info file."""
411
412
413class InadequateHostsException(CrosDynamicSuiteException):
414    """Raised when there are too few hosts to run a suite."""
415
416
417class NoHostsException(CrosDynamicSuiteException):
418    """Raised when there are no healthy hosts to run a suite."""
419
420
421class ControlFileNotFound(CrosDynamicSuiteException):
422    """Raised when a control file cannot be found and/or read."""
423
424
425class NoControlFileList(CrosDynamicSuiteException):
426    """Raised to indicate that a listing can't be done."""
427
428
429class SuiteControlFileException(CrosDynamicSuiteException):
430    """Raised when failing to list the contents of all control file."""
431
432
433class HostLockManagerReuse(CrosDynamicSuiteException):
434    """Raised when a caller tries to re-use a HostLockManager instance."""
435
436
437class ReimageAbortedException(CrosDynamicSuiteException):
438    """Raised when a Reimage job is aborted"""
439
440
441class UnknownReimageType(CrosDynamicSuiteException):
442    """Raised when a suite passes in an invalid reimage type"""
443
444
445class NoUniquePackageFound(Exception):
446    """Raised when an executable cannot be mapped back to a single package."""
447
448
449class RPCException(Exception):
450    """Raised when an RPC encounters an error that a client might wish to
451    handle specially."""
452
453
454class NoEligibleHostException(RPCException):
455    """Raised when no host could satisfy the requirements of a job."""
456
457
458class InvalidBgJobCall(Exception):
459    """Raised when an invalid call is made to a BgJob object."""
460
461
462class HeartbeatOnlyAllowedInShardModeException(Exception):
463    """Raised when a heartbeat is attempted but not allowed."""
464
465
466class UnallowedRecordsSentToMaster(Exception):
467    """Raised when an illegal record was sent from shard to master."""
468
469
470class IgnorableUnallowedRecordsSentToMaster(UnallowedRecordsSentToMaster):
471    """Raised when non-fatal illegal record was sent from shard.
472
473    This exception may be raised by rpc model logic on master, but will
474    not be returned back to heartbeat client. It indicates that some records
475    may have been illegal, but the master is ignoring those records and
476    proceeding with the rest of the heartbeat handling.
477    """
478
479
480class InvalidDataError(Exception):
481    """Exception raised when invalid data provided for database operation."""
482
483
484class ContainerError(Exception):
485    """Exception raised when program runs into error using container."""
486
487
488class IllegalUser(Exception):
489    """Exception raise when a program runs as an illegal user."""
490
491
492# This MUST remain at the end of the file.
493# Limit 'from error import *' to only import the exception instances.
494for _name, _thing in locals().items():
495    try:
496        if issubclass(_thing, Exception):
497            __all__.append(_name)
498    except TypeError:
499        pass  # _thing not a class
500__all__ = tuple(__all__)
501