• 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 UnhandledTestError(TestError):
90    """Indicates an unhandled error in a test."""
91    def __init__(self, unhandled_exception):
92        if isinstance(unhandled_exception, TestError):
93            TestError.__init__(self, *unhandled_exception.args)
94        elif isinstance(unhandled_exception, basestring):
95            TestError.__init__(self, unhandled_exception)
96        else:
97            msg = "Unhandled %s: %s"
98            msg %= (unhandled_exception.__class__.__name__,
99                    unhandled_exception)
100            msg += "\n" + traceback.format_exc()
101            TestError.__init__(self, msg)
102
103
104class UnhandledTestFail(TestFail):
105    """Indicates an unhandled fail in a test."""
106    def __init__(self, unhandled_exception):
107        if isinstance(unhandled_exception, TestFail):
108            TestFail.__init__(self, *unhandled_exception.args)
109        elif isinstance(unhandled_exception, basestring):
110            TestFail.__init__(self, unhandled_exception)
111        else:
112            msg = "Unhandled %s: %s"
113            msg %= (unhandled_exception.__class__.__name__,
114                    unhandled_exception)
115            msg += "\n" + traceback.format_exc()
116            TestFail.__init__(self, msg)
117
118
119class CmdError(TestError):
120    """Indicates that a command failed, is fatal to the test unless caught.
121
122    @type command: str
123    @type result_obj: autotest_lib.client.common_lib.utils.CmdResult
124    @type additional_text: str | None
125    """
126    def __init__(self, command, result_obj, additional_text=None):
127        TestError.__init__(self, command, result_obj, additional_text)
128        self.command = command
129        self.result_obj = result_obj
130        self.additional_text = additional_text
131
132    def __str__(self):
133        if self.result_obj.exit_status is None:
134            msg = "Command <%s> failed and is not responding to signals"
135            msg %= self.command
136        else:
137            msg = "Command <%s> failed, rc=%d"
138            msg %= (self.command, self.result_obj.exit_status)
139
140        if self.additional_text:
141            msg += ", " + self.additional_text
142        msg += '\n' + repr(self.result_obj)
143        return msg
144
145    def __eq__(self, other):
146        if type(self) == type(other):
147            return (self.command == other.command
148                    and self.result_obj == other.result_obj
149                    and self.additional_text == other.additional_text)
150        else:
151            return NotImplemented
152
153
154class CmdTimeoutError(CmdError):
155    """Indicates that a command timed out."""
156
157
158class PackageError(TestError):
159    """Indicates an error trying to perform a package operation."""
160
161
162class BarrierError(JobError):
163    """Indicates an error happened during a barrier operation."""
164
165
166class BarrierAbortError(BarrierError):
167    """Indicate that the barrier was explicitly aborted by a member."""
168
169
170class InstallError(JobError):
171    """Indicates an installation error which Terminates and fails the job."""
172
173
174class AutotestRunError(AutotestError):
175    """Indicates a problem running server side control files."""
176
177
178class AutotestTimeoutError(AutotestError):
179    """This exception is raised when an autotest test exceeds the timeout
180    parameter passed to run_timed_test and is killed.
181    """
182
183
184class GenericHostRunError(Exception):
185    """Indicates a problem in the host run() function running in either client
186    or server code.
187
188    Should always be constructed with a tuple of two args (error description
189    (str), run result object). This is a common class used to create the client
190    and server side versions of it when the distinction is useful.
191    """
192    def __init__(self, description, result_obj):
193        self.description = description
194        self.result_obj = result_obj
195        Exception.__init__(self, description, result_obj)
196
197    def __str__(self):
198        return self.description + '\n' + repr(self.result_obj)
199
200
201class HostInstallTimeoutError(JobError):
202    """
203    Indicates the machine failed to be installed after the predetermined
204    timeout.
205    """
206
207
208class AutotestHostRunError(GenericHostRunError, AutotestError):
209    pass
210
211
212class AutotestHostRunCmdError(AutotestHostRunError):
213    """Indicates that the command run via Host.run failed.
214
215    This is equivalent to CmdError when raised from a Host object instead of
216    directly on the DUT using utils.run
217    """
218
219    def __init__(self, command, result_obj, additional_text=''):
220        description = command
221        if additional_text:
222            description += ' (%s)' % additional_text
223        super(AutotestHostRunCmdError, self).__init__(description, result_obj)
224        self.command = command
225        self.additional_text = additional_text
226
227
228class AutotestHostRunTimeoutError(AutotestHostRunCmdError):
229    """Indicates that a command run via Host.run timed out.
230
231    This is equivalent to CmdTimeoutError when raised from a Host object instead
232    of directly on the DUT using utils.run
233    """
234
235
236# server-specific errors
237
238class AutoservError(Exception):
239    pass
240
241
242class AutoservSSHTimeout(AutoservError):
243    """SSH experienced a connection timeout"""
244
245
246class AutoservRunError(GenericHostRunError, AutoservError):
247    pass
248
249
250class AutoservSshPermissionDeniedError(AutoservRunError):
251    """Indicates that a SSH permission denied error was encountered."""
252
253
254class AutoservUnsupportedError(AutoservError):
255    """Error raised when you try to use an unsupported optional feature"""
256
257
258class AutoservHostError(AutoservError):
259    """Error reaching a host"""
260
261
262class AutoservHostIsShuttingDownError(AutoservHostError):
263    """Host is shutting down"""
264
265
266class AutoservNotMountedHostError(AutoservHostError):
267    """Found unmounted partitions that should be mounted"""
268
269
270class AutoservSshPingHostError(AutoservHostError):
271    """SSH ping failed"""
272
273
274class AutoservDiskFullHostError(AutoservHostError):
275    """Not enough free disk space on host"""
276
277    def __init__(self, path, want_gb, free_space_gb):
278        super(AutoservDiskFullHostError, self).__init__(
279            'Not enough free space on %s - %.3fGB free, want %.3fGB' %
280                    (path, free_space_gb, want_gb))
281        self.path = path
282        self.want_gb = want_gb
283        self.free_space_gb = free_space_gb
284
285
286class AutoservNoFreeInodesError(AutoservHostError):
287    """Not enough free i-nodes on host"""
288
289    def __init__(self, path, want_inodes, free_inodes):
290        super(AutoservNoFreeInodesError, self).__init__(
291            'Not enough free inodes on %s - %d free, want %d' %
292                    (path, free_inodes, want_inodes))
293        self.path = path
294        self.want_inodes = want_inodes
295        self.free_inodes = free_inodes
296
297
298class AutoservHardwareHostError(AutoservHostError):
299    """Found hardware problems with the host"""
300
301
302class AutoservRebootError(AutoservError):
303    """Error occured while rebooting a machine"""
304
305
306class AutoservShutdownError(AutoservRebootError):
307    """Error occured during shutdown of machine"""
308
309
310class AutoservSuspendError(AutoservRebootError):
311    """Error occured while suspending a machine"""
312
313
314class AutoservSubcommandError(AutoservError):
315    """Indicates an error while executing a (forked) subcommand"""
316    def __init__(self, func, exit_code):
317        AutoservError.__init__(self, func, exit_code)
318        self.func = func
319        self.exit_code = exit_code
320
321    def __str__(self):
322        return ("Subcommand %s failed with exit code %d" %
323                (self.func, self.exit_code))
324
325
326class AutoservRepairTotalFailure(AutoservError):
327    """Raised if all attempts to repair the DUT failed."""
328
329
330class AutoservInstallError(AutoservError):
331    """Error occured while installing autotest on a host"""
332
333
334class AutoservPidAlreadyDeadError(AutoservError):
335    """Error occured by trying to kill a nonexistant PID"""
336
337
338# packaging system errors
339
340class PackagingError(AutotestError):
341    'Abstract error class for all packaging related errors.'
342
343
344class PackageUploadError(PackagingError):
345    'Raised when there is an error uploading the package'
346
347
348class PackageFetchError(PackagingError):
349    'Raised when there is an error fetching the package'
350
351
352class PackageRemoveError(PackagingError):
353    'Raised when there is an error removing the package'
354
355
356class PackageInstallError(PackagingError):
357    'Raised when there is an error installing the package'
358
359
360class RepoDiskFullError(PackagingError):
361    'Raised when the destination for packages is full'
362
363
364class RepoWriteError(PackagingError):
365    "Raised when packager cannot write to a repo's desitnation"
366
367
368class RepoUnknownError(PackagingError):
369    "Raised when packager cannot write to a repo's desitnation"
370
371
372class RepoError(PackagingError):
373    "Raised when a repo isn't working in some way"
374
375
376class StageControlFileFailure(Exception):
377    """Exceptions encountered staging control files."""
378
379
380class CrosDynamicSuiteException(Exception):
381    """
382    Base class for exceptions coming from dynamic suite code in
383    server/cros/dynamic_suite/*.
384    """
385
386
387class StageBuildFailure(CrosDynamicSuiteException):
388    """Raised when the dev server throws 500 while staging a build."""
389
390
391class ControlFileEmpty(CrosDynamicSuiteException):
392    """Raised when the control file exists on the server, but can't be read."""
393
394
395class ControlFileMalformed(CrosDynamicSuiteException):
396    """Raised when an invalid control file is read."""
397
398
399class AsynchronousBuildFailure(CrosDynamicSuiteException):
400    """Raised when the dev server throws 500 while finishing staging of a build.
401    """
402
403
404class SuiteArgumentException(CrosDynamicSuiteException):
405    """Raised when improper arguments are used to run a suite."""
406
407
408class MalformedDependenciesException(CrosDynamicSuiteException):
409    """Raised when a build has a malformed dependency_info file."""
410
411
412class InadequateHostsException(CrosDynamicSuiteException):
413    """Raised when there are too few hosts to run a suite."""
414
415
416class NoHostsException(CrosDynamicSuiteException):
417    """Raised when there are no healthy hosts to run a suite."""
418
419
420class ControlFileNotFound(CrosDynamicSuiteException):
421    """Raised when a control file cannot be found and/or read."""
422
423
424class NoControlFileList(CrosDynamicSuiteException):
425    """Raised to indicate that a listing can't be done."""
426
427
428class SuiteControlFileException(CrosDynamicSuiteException):
429    """Raised when failing to list the contents of all control file."""
430
431
432class HostLockManagerReuse(CrosDynamicSuiteException):
433    """Raised when a caller tries to re-use a HostLockManager instance."""
434
435
436class ReimageAbortedException(CrosDynamicSuiteException):
437    """Raised when a Reimage job is aborted"""
438
439
440class UnknownReimageType(CrosDynamicSuiteException):
441    """Raised when a suite passes in an invalid reimage type"""
442
443
444class NoUniquePackageFound(Exception):
445    """Raised when an executable cannot be mapped back to a single package."""
446
447
448class RPCException(Exception):
449    """Raised when an RPC encounters an error that a client might wish to
450    handle specially."""
451
452
453class NoEligibleHostException(RPCException):
454    """Raised when no host could satisfy the requirements of a job."""
455
456
457class UnmodifiableLabelException(RPCException):
458    """Raised when an RPC tries to modify static labels."""
459
460
461class UnmodifiableAttributeException(RPCException):
462    """Raised when an RPC tries to modify static attributes."""
463
464
465class InvalidBgJobCall(Exception):
466    """Raised when an invalid call is made to a BgJob object."""
467
468
469class HeartbeatOnlyAllowedInShardModeException(Exception):
470    """Raised when a heartbeat is attempted but not allowed."""
471
472
473class UnallowedRecordsSentToMaster(Exception):
474    """Raised when an illegal record was sent from shard to master."""
475
476
477class IgnorableUnallowedRecordsSentToMaster(UnallowedRecordsSentToMaster):
478    """Raised when non-fatal illegal record was sent from shard.
479
480    This exception may be raised by rpc model logic on master, but will
481    not be returned back to heartbeat client. It indicates that some records
482    may have been illegal, but the master is ignoring those records and
483    proceeding with the rest of the heartbeat handling.
484    """
485
486
487class InvalidDataError(Exception):
488    """Exception raised when invalid data provided for database operation."""
489
490
491class ContainerError(Exception):
492    """Exception raised when program runs into error using container."""
493
494
495class IllegalUser(Exception):
496    """Exception raise when a program runs as an illegal user."""
497
498
499class AutoservDirectoryNotFoundError(AutoservHostError):
500    """Exception raised when an expected directory is not found."""
501
502
503class AutoservDiskSizeUnknownError(AutoservHostError):
504    """Exception raised when the disk space could not be determined."""
505
506
507# This MUST remain at the end of the file.
508# Limit 'from error import *' to only import the exception instances.
509for _name, _thing in locals().items():
510    try:
511        if issubclass(_thing, Exception):
512            __all__.append(_name)
513    except TypeError:
514        pass  # _thing not a class
515__all__ = tuple(__all__)
516