blob: 543bea91eb1d723c04de312e3560ab080cc72519 [file] [log] [blame]
Aviv Keshet39164ca2013-03-27 15:08:33 -07001#pylint: disable-msg=C0111
2
mbligh906b9f72007-11-29 18:56:17 +00003"""
4Internal global error types
5"""
6
Alex Miller30837902013-02-02 15:52:43 -08007import sys, traceback, threading
mbligh906b9f72007-11-29 18:56:17 +00008from traceback import format_exception
9
mbligh91672252008-10-16 22:28:34 +000010# 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.
Eric Li861b2d52011-02-04 14:50:35 -080013__all__ = ['format_error', 'context_aware', 'context', 'get_context',
14 'exception_context']
mbligh91672252008-10-16 22:28:34 +000015
16
mbligh906b9f72007-11-29 18:56:17 +000017def format_error():
jadmanski0afbb632008-06-06 21:10:57 +000018 t, o, tb = sys.exc_info()
19 trace = format_exception(t, o, tb)
20 # Clear the backtrace to prevent a circular reference
21 # in the heap -- as per tutorial
22 tb = ''
mbligh906b9f72007-11-29 18:56:17 +000023
jadmanski0afbb632008-06-06 21:10:57 +000024 return ''.join(trace)
mbligh906b9f72007-11-29 18:56:17 +000025
mbligh4f407462008-12-03 15:22:39 +000026
Eric Li861b2d52011-02-04 14:50:35 -080027# Exception context information:
28# ------------------------------
29# Every function can have some context string associated with it.
30# The context string can be changed by calling context(str) and cleared by
31# calling context() with no parameters.
32# get_context() joins the current context strings of all functions in the
33# provided traceback. The result is a brief description of what the test was
34# doing in the provided traceback (which should be the traceback of a caught
35# exception).
36#
37# For example: assume a() calls b() and b() calls c().
38#
39# @error.context_aware
40# def a():
41# error.context("hello")
42# b()
43# error.context("world")
44# error.get_context() ----> 'world'
45#
46# @error.context_aware
47# def b():
48# error.context("foo")
49# c()
50#
51# @error.context_aware
52# def c():
53# error.context("bar")
54# error.get_context() ----> 'hello --> foo --> bar'
55#
56# The current context is automatically inserted into exceptions raised in
57# context_aware functions, so usually test code doesn't need to call
58# error.get_context().
59
60ctx = threading.local()
61
62
63def _new_context(s=""):
64 if not hasattr(ctx, "contexts"):
65 ctx.contexts = []
66 ctx.contexts.append(s)
67
68
69def _pop_context():
70 ctx.contexts.pop()
71
72
73def context(s="", log=None):
74 """
75 Set the context for the currently executing function and optionally log it.
76
77 @param s: A string. If not provided, the context for the current function
78 will be cleared.
79 @param log: A logging function to pass the context message to. If None, no
80 function will be called.
81 """
82 ctx.contexts[-1] = s
83 if s and log:
84 log("Context: %s" % get_context())
85
86
87def base_context(s="", log=None):
88 """
89 Set the base context for the currently executing function and optionally
90 log it. The base context is just another context level that is hidden by
91 default. Functions that require a single context level should not use
92 base_context().
93
94 @param s: A string. If not provided, the base context for the current
95 function will be cleared.
96 @param log: A logging function to pass the context message to. If None, no
97 function will be called.
98 """
99 ctx.contexts[-1] = ""
100 ctx.contexts[-2] = s
101 if s and log:
102 log("Context: %s" % get_context())
103
104
105def get_context():
106 """Return the current context (or None if none is defined)."""
107 if hasattr(ctx, "contexts"):
108 return " --> ".join([s for s in ctx.contexts if s])
109
110
111def exception_context(e):
112 """Return the context of a given exception (or None if none is defined)."""
113 if hasattr(e, "_context"):
Alex Miller30837902013-02-02 15:52:43 -0800114 return e._context # pylint: disable=W0212
Eric Li861b2d52011-02-04 14:50:35 -0800115
116
117def set_exception_context(e, s):
118 """Set the context of a given exception."""
119 e._context = s
120
121
122def join_contexts(s1, s2):
123 """Join two context strings."""
124 if s1:
125 if s2:
126 return "%s --> %s" % (s1, s2)
127 else:
128 return s1
129 else:
130 return s2
131
132
133def context_aware(fn):
134 """A decorator that must be applied to functions that call context()."""
135 def new_fn(*args, **kwargs):
136 _new_context()
137 _new_context("(%s)" % fn.__name__)
138 try:
139 try:
140 return fn(*args, **kwargs)
141 except Exception, e:
142 if not exception_context(e):
143 set_exception_context(e, get_context())
144 raise
145 finally:
146 _pop_context()
147 _pop_context()
148 new_fn.__name__ = fn.__name__
149 new_fn.__doc__ = fn.__doc__
150 new_fn.__dict__.update(fn.__dict__)
151 return new_fn
152
153
154def _context_message(e):
155 s = exception_context(e)
156 if s:
157 return " [context: %s]" % s
158 else:
159 return ""
160
161
beeps60aec242013-06-26 14:47:48 -0700162
163class TimeoutException(Exception):
164 """
165 Generic exception raised on retry timeouts.
166 """
167 pass
168
169
mbligh906b9f72007-11-29 18:56:17 +0000170class JobContinue(SystemExit):
jadmanski0afbb632008-06-06 21:10:57 +0000171 """Allow us to bail out requesting continuance."""
172 pass
mbligh906b9f72007-11-29 18:56:17 +0000173
mbligh7e1b1502008-06-06 15:05:41 +0000174
mbligh906b9f72007-11-29 18:56:17 +0000175class JobComplete(SystemExit):
jadmanski0afbb632008-06-06 21:10:57 +0000176 """Allow us to bail out indicating continuation not required."""
177 pass
mbligh906b9f72007-11-29 18:56:17 +0000178
mbligh7e1b1502008-06-06 15:05:41 +0000179
mbligh906b9f72007-11-29 18:56:17 +0000180class AutotestError(Exception):
jadmanski0afbb632008-06-06 21:10:57 +0000181 """The parent of all errors deliberatly thrown within the client code."""
Eric Li861b2d52011-02-04 14:50:35 -0800182 def __str__(self):
183 return Exception.__str__(self) + _context_message(self)
mbligh906b9f72007-11-29 18:56:17 +0000184
mbligh7e1b1502008-06-06 15:05:41 +0000185
mbligh906b9f72007-11-29 18:56:17 +0000186class JobError(AutotestError):
mbligh4f407462008-12-03 15:22:39 +0000187 """Indicates an error which terminates and fails the whole job (ABORT)."""
jadmanski0afbb632008-06-06 21:10:57 +0000188 pass
mbligh906b9f72007-11-29 18:56:17 +0000189
mbligh7e1b1502008-06-06 15:05:41 +0000190
mbligh4f407462008-12-03 15:22:39 +0000191class UnhandledJobError(JobError):
192 """Indicates an unhandled error in a job."""
193 def __init__(self, unhandled_exception):
194 if isinstance(unhandled_exception, JobError):
mbligh1ca1c2c2008-12-09 23:38:25 +0000195 JobError.__init__(self, *unhandled_exception.args)
Eric Li861b2d52011-02-04 14:50:35 -0800196 elif isinstance(unhandled_exception, str):
197 JobError.__init__(self, unhandled_exception)
mbligh4f407462008-12-03 15:22:39 +0000198 else:
199 msg = "Unhandled %s: %s"
200 msg %= (unhandled_exception.__class__.__name__,
201 unhandled_exception)
Eric Li861b2d52011-02-04 14:50:35 -0800202 if not isinstance(unhandled_exception, AutotestError):
203 msg += _context_message(unhandled_exception)
mbligh4f407462008-12-03 15:22:39 +0000204 msg += "\n" + traceback.format_exc()
205 JobError.__init__(self, msg)
206
207
mblighc2180832008-07-25 03:26:12 +0000208class TestBaseException(AutotestError):
209 """The parent of all test exceptions."""
mbligh021679f2008-11-27 00:43:19 +0000210 # Children are required to override this. Never instantiate directly.
Alex Miller30837902013-02-02 15:52:43 -0800211 exit_status = "NEVER_RAISE_THIS"
mblighc2180832008-07-25 03:26:12 +0000212
213
214class TestError(TestBaseException):
mblighb48fa562008-06-23 17:29:40 +0000215 """Indicates that something went wrong with the test harness itself."""
Alex Miller30837902013-02-02 15:52:43 -0800216 exit_status = "ERROR"
mblighb48fa562008-06-23 17:29:40 +0000217
jadmanski8d01bfe2008-06-23 18:13:24 +0000218
mblighc2180832008-07-25 03:26:12 +0000219class TestNAError(TestBaseException):
jadmanski0afbb632008-06-06 21:10:57 +0000220 """Indictates that the test is Not Applicable. Should be thrown
mblighb48fa562008-06-23 17:29:40 +0000221 when various conditions are such that the test is inappropriate."""
Alex Miller30837902013-02-02 15:52:43 -0800222 exit_status = "TEST_NA"
mblighb48fa562008-06-23 17:29:40 +0000223
jadmanski8d01bfe2008-06-23 18:13:24 +0000224
mblighc2180832008-07-25 03:26:12 +0000225class TestFail(TestBaseException):
mblighb48fa562008-06-23 17:29:40 +0000226 """Indicates that the test failed, but the job will not continue."""
Alex Miller30837902013-02-02 15:52:43 -0800227 exit_status = "FAIL"
mblighb48fa562008-06-23 17:29:40 +0000228
jadmanski8d01bfe2008-06-23 18:13:24 +0000229
mblighc2180832008-07-25 03:26:12 +0000230class TestWarn(TestBaseException):
mblighb48fa562008-06-23 17:29:40 +0000231 """Indicates that bad things (may) have happened, but not an explicit
232 failure."""
Alex Miller30837902013-02-02 15:52:43 -0800233 exit_status = "WARN"
mbligh6a2a2df2008-01-16 17:41:55 +0000234
mbligh7e1b1502008-06-06 15:05:41 +0000235
Aviv Keshet39164ca2013-03-27 15:08:33 -0700236class TestFailRetry(TestFail):
237 """Indicates that the test failed, but in a manner that may be retried
238 if test retries are enabled for this test."""
239 exit_status = "FAIL"
240
241
mblighc2180832008-07-25 03:26:12 +0000242class UnhandledTestError(TestError):
243 """Indicates an unhandled error in a test."""
244 def __init__(self, unhandled_exception):
245 if isinstance(unhandled_exception, TestError):
246 TestError.__init__(self, *unhandled_exception.args)
Eric Li861b2d52011-02-04 14:50:35 -0800247 elif isinstance(unhandled_exception, str):
248 TestError.__init__(self, unhandled_exception)
mblighc2180832008-07-25 03:26:12 +0000249 else:
250 msg = "Unhandled %s: %s"
251 msg %= (unhandled_exception.__class__.__name__,
252 unhandled_exception)
Eric Li861b2d52011-02-04 14:50:35 -0800253 if not isinstance(unhandled_exception, AutotestError):
254 msg += _context_message(unhandled_exception)
mblighc2180832008-07-25 03:26:12 +0000255 msg += "\n" + traceback.format_exc()
256 TestError.__init__(self, msg)
257
258
259class UnhandledTestFail(TestFail):
260 """Indicates an unhandled fail in a test."""
261 def __init__(self, unhandled_exception):
262 if isinstance(unhandled_exception, TestFail):
263 TestFail.__init__(self, *unhandled_exception.args)
Eric Li861b2d52011-02-04 14:50:35 -0800264 elif isinstance(unhandled_exception, str):
265 TestFail.__init__(self, unhandled_exception)
mblighc2180832008-07-25 03:26:12 +0000266 else:
267 msg = "Unhandled %s: %s"
268 msg %= (unhandled_exception.__class__.__name__,
269 unhandled_exception)
Eric Li861b2d52011-02-04 14:50:35 -0800270 if not isinstance(unhandled_exception, AutotestError):
271 msg += _context_message(unhandled_exception)
mblighc2180832008-07-25 03:26:12 +0000272 msg += "\n" + traceback.format_exc()
273 TestFail.__init__(self, msg)
274
275
mbligh906b9f72007-11-29 18:56:17 +0000276class CmdError(TestError):
jadmanski0afbb632008-06-06 21:10:57 +0000277 """\
278 Indicates that a command failed, is fatal to the test unless caught.
279 """
280 def __init__(self, command, result_obj, additional_text=None):
281 TestError.__init__(self, command, result_obj, additional_text)
mblighc23051c2008-06-27 19:26:46 +0000282 self.command = command
283 self.result_obj = result_obj
284 self.additional_text = additional_text
mbligh6a2a2df2008-01-16 17:41:55 +0000285
jadmanski0afbb632008-06-06 21:10:57 +0000286 def __str__(self):
jadmanski6ef0b672008-09-30 22:50:19 +0000287 if self.result_obj.exit_status is None:
288 msg = "Command <%s> failed and is not responding to signals"
289 msg %= self.command
290 else:
291 msg = "Command <%s> failed, rc=%d"
292 msg %= (self.command, self.result_obj.exit_status)
293
mblighc23051c2008-06-27 19:26:46 +0000294 if self.additional_text:
295 msg += ", " + self.additional_text
Eric Li861b2d52011-02-04 14:50:35 -0800296 msg += _context_message(self)
showard6d7e94f2008-08-20 20:53:34 +0000297 msg += '\n' + repr(self.result_obj)
jadmanski0afbb632008-06-06 21:10:57 +0000298 return msg
mbligh906b9f72007-11-29 18:56:17 +0000299
mbligh7e1b1502008-06-06 15:05:41 +0000300
mbligh906b9f72007-11-29 18:56:17 +0000301class PackageError(TestError):
jadmanski0afbb632008-06-06 21:10:57 +0000302 """Indicates an error trying to perform a package operation."""
303 pass
mbligh906b9f72007-11-29 18:56:17 +0000304
mbligh7e1b1502008-06-06 15:05:41 +0000305
mblighe8673102008-07-16 14:09:03 +0000306class BarrierError(JobError):
307 """Indicates an error happened during a barrier operation."""
308 pass
309
310
mbligh999fb132010-04-23 17:22:03 +0000311class BarrierAbortError(BarrierError):
312 """Indicate that the barrier was explicitly aborted by a member."""
313 pass
314
315
mbligh5deff3d2008-01-04 21:21:28 +0000316class InstallError(JobError):
jadmanski0afbb632008-06-06 21:10:57 +0000317 """Indicates an installation error which Terminates and fails the job."""
318 pass
mbligh03f4fc72007-11-29 20:56:14 +0000319
mbligh7e1b1502008-06-06 15:05:41 +0000320
mbligh6f015c42008-02-12 20:55:03 +0000321class AutotestRunError(AutotestError):
mbligh021679f2008-11-27 00:43:19 +0000322 """Indicates a problem running server side control files."""
jadmanski0afbb632008-06-06 21:10:57 +0000323 pass
mbligh6f015c42008-02-12 20:55:03 +0000324
mbligh7e1b1502008-06-06 15:05:41 +0000325
mbligh6f015c42008-02-12 20:55:03 +0000326class AutotestTimeoutError(AutotestError):
jadmanski0afbb632008-06-06 21:10:57 +0000327 """This exception is raised when an autotest test exceeds the timeout
328 parameter passed to run_timed_test and is killed.
329 """
Dale Curtis8adf7892011-09-08 16:13:36 -0700330 pass
mbligh6f015c42008-02-12 20:55:03 +0000331
332
mblighce955fc2009-08-24 21:59:02 +0000333class HostRunErrorMixIn(Exception):
334 """
335 Indicates a problem in the host run() function raised from client code.
336 Should always be constructed with a tuple of two args (error description
337 (str), run result object). This is a common class mixed in to create the
338 client and server side versions of it.
339 """
340 def __init__(self, description, result_obj):
341 self.description = description
342 self.result_obj = result_obj
343 Exception.__init__(self, description, result_obj)
344
345 def __str__(self):
346 return self.description + '\n' + repr(self.result_obj)
347
348
Dale Curtis8adf7892011-09-08 16:13:36 -0700349class HostInstallTimeoutError(JobError):
350 """
351 Indicates the machine failed to be installed after the predetermined
352 timeout.
353 """
354 pass
355
356
mblighce955fc2009-08-24 21:59:02 +0000357class AutotestHostRunError(HostRunErrorMixIn, AutotestError):
358 pass
359
360
mbligh03f4fc72007-11-29 20:56:14 +0000361# server-specific errors
362
363class AutoservError(Exception):
jadmanski0afbb632008-06-06 21:10:57 +0000364 pass
mbligh03f4fc72007-11-29 20:56:14 +0000365
366
mbligh34faa282008-01-16 17:44:49 +0000367class AutoservSSHTimeout(AutoservError):
jadmanski0afbb632008-06-06 21:10:57 +0000368 """SSH experienced a connection timeout"""
369 pass
mbligh34faa282008-01-16 17:44:49 +0000370
371
mblighce955fc2009-08-24 21:59:02 +0000372class AutoservRunError(HostRunErrorMixIn, AutoservError):
373 pass
showard6d7e94f2008-08-20 20:53:34 +0000374
mbligh03f4fc72007-11-29 20:56:14 +0000375
mbligh9d738d62009-03-09 21:17:10 +0000376class AutoservSshPermissionDeniedError(AutoservRunError):
377 """Indicates that a SSH permission denied error was encountered."""
378 pass
379
380
mbligh03f4fc72007-11-29 20:56:14 +0000381class AutoservVirtError(AutoservError):
jadmanski0afbb632008-06-06 21:10:57 +0000382 """Vitualization related error"""
383 pass
mbligh03f4fc72007-11-29 20:56:14 +0000384
385
386class AutoservUnsupportedError(AutoservError):
jadmanski0afbb632008-06-06 21:10:57 +0000387 """Error raised when you try to use an unsupported optional feature"""
388 pass
mbligh03f4fc72007-11-29 20:56:14 +0000389
mbligh7e1b1502008-06-06 15:05:41 +0000390
mbligh03f4fc72007-11-29 20:56:14 +0000391class AutoservHostError(AutoservError):
jadmanski0afbb632008-06-06 21:10:57 +0000392 """Error reaching a host"""
393 pass
mbligh03f4fc72007-11-29 20:56:14 +0000394
mbligh7e1b1502008-06-06 15:05:41 +0000395
mblighc971c5f2009-06-08 16:48:54 +0000396class AutoservHostIsShuttingDownError(AutoservHostError):
397 """Host is shutting down"""
398 pass
399
400
401class AutoservNotMountedHostError(AutoservHostError):
402 """Found unmounted partitions that should be mounted"""
403 pass
404
405
406class AutoservSshPingHostError(AutoservHostError):
407 """SSH ping failed"""
408 pass
409
410
411class AutoservDiskFullHostError(AutoservHostError):
412 """Not enough free disk space on host"""
413 def __init__(self, path, want_gb, free_space_gb):
414 AutoservHostError.__init__(self,
415 'Not enough free space on %s - %.3fGB free, want %.3fGB' %
416 (path, free_space_gb, want_gb))
417
418 self.path = path
419 self.want_gb = want_gb
420 self.free_space_gb = free_space_gb
421
422
423class AutoservHardwareHostError(AutoservHostError):
424 """Found hardware problems with the host"""
425 pass
426
427
mbligh03f4fc72007-11-29 20:56:14 +0000428class AutoservRebootError(AutoservError):
jadmanski0afbb632008-06-06 21:10:57 +0000429 """Error occured while rebooting a machine"""
430 pass
mbligh6e2ffec2008-03-05 16:08:34 +0000431
mbligh7e1b1502008-06-06 15:05:41 +0000432
jadmanski65eb8f52009-07-24 18:34:43 +0000433class AutoservShutdownError(AutoservRebootError):
434 """Error occured during shutdown of machine"""
435 pass
436
437
mbligh6e2ffec2008-03-05 16:08:34 +0000438class AutoservSubcommandError(AutoservError):
jadmanski0afbb632008-06-06 21:10:57 +0000439 """Indicates an error while executing a (forked) subcommand"""
440 def __init__(self, func, exit_code):
441 AutoservError.__init__(self, func, exit_code)
442 self.func = func
443 self.exit_code = exit_code
mbligh7e1b1502008-06-06 15:05:41 +0000444
jadmanski0afbb632008-06-06 21:10:57 +0000445 def __str__(self):
446 return ("Subcommand %s failed with exit code %d" %
447 (self.func, self.exit_code))
mbligh91672252008-10-16 22:28:34 +0000448
449
Scott Zawalski62bacae2013-03-05 10:40:32 -0500450class AutoservRepairTotalFailure(AutoservError):
451 """Raised if all attempts to repair the DUT failed."""
452 pass
453
454
455class AutoservRepairFailure(AutoservError):
456 """Raised by a repair method if it is unable to repair a DUT."""
457 pass
458
459
460class AutoservRepairMethodNA(AutoservError):
461 """Raised when for any reason a praticular repair method is NA."""
462 pass
463
464
mbligh25c0b8c2009-01-24 01:44:17 +0000465class AutoservHardwareRepairRequestedError(AutoservError):
466 """
467 Exception class raised from Host.repair_full() (or overrides) when software
468 repair fails but it successfully managed to request a hardware repair (by
469 notifying the staff, sending mail, etc)
470 """
471 pass
472
473
jadmanski2615f4a2010-07-19 16:39:56 +0000474class AutoservHardwareRepairRequiredError(AutoservError):
475 """
476 Exception class raised during repairs to indicate that a hardware repair
477 is going to be necessary.
478 """
479 pass
480
481
jadmanskic1dda212009-11-18 19:22:00 +0000482class AutoservInstallError(AutoservError):
483 """Error occured while installing autotest on a host"""
484 pass
485
486
Simran Basi31cf2bd2012-08-14 16:51:54 -0700487class AutoservPidAlreadyDeadError(AutoservError):
488 """Error occured by trying to kill a nonexistant PID"""
489 pass
490
491
jadmanskic27c2312009-08-05 20:58:51 +0000492# packaging system errors
493
494class PackagingError(AutotestError):
495 'Abstract error class for all packaging related errors.'
496
497
498class PackageUploadError(PackagingError):
499 'Raised when there is an error uploading the package'
500
501
502class PackageFetchError(PackagingError):
503 'Raised when there is an error fetching the package'
504
505
506class PackageRemoveError(PackagingError):
507 'Raised when there is an error removing the package'
508
509
510class PackageInstallError(PackagingError):
511 'Raised when there is an error installing the package'
512
513
514class RepoDiskFullError(PackagingError):
515 'Raised when the destination for packages is full'
516
517
518class RepoWriteError(PackagingError):
519 "Raised when packager cannot write to a repo's desitnation"
520
521
522class RepoUnknownError(PackagingError):
523 "Raised when packager cannot write to a repo's desitnation"
524
525
526class RepoError(PackagingError):
527 "Raised when a repo isn't working in some way"
528
529
Chris Masonef8b53062012-05-08 22:14:18 -0700530class CrosDynamicSuiteException(Exception):
531 """
Chris Masoneb4935552012-08-14 12:05:54 -0700532 Base class for exceptions coming from dynamic suite code in
533 server/cros/dynamic_suite/*.
Chris Masonef8b53062012-05-08 22:14:18 -0700534 """
535 pass
536
537
538class StageBuildFailure(CrosDynamicSuiteException):
539 """Raised when the dev server throws 500 while staging a build."""
540 pass
541
542
543class ControlFileEmpty(CrosDynamicSuiteException):
544 """Raised when the control file exists on the server, but can't be read."""
545 pass
546
547
Alex Millera713e252013-03-01 10:45:44 -0800548class ControlFileMalformed(CrosDynamicSuiteException):
549 """Raised when an invalid control file is read."""
550 pass
551
552
Chris Masonef8b53062012-05-08 22:14:18 -0700553class AsynchronousBuildFailure(CrosDynamicSuiteException):
554 """Raised when the dev server throws 500 while finishing staging of a build.
555 """
556 pass
557
558
559class SuiteArgumentException(CrosDynamicSuiteException):
560 """Raised when improper arguments are used to run a suite."""
561 pass
562
563
Chris Masone8906ab12012-07-23 15:37:56 -0700564class MalformedDependenciesException(CrosDynamicSuiteException):
565 """Raised when a build has a malformed dependency_info file."""
566 pass
567
568
Chris Masonef8b53062012-05-08 22:14:18 -0700569class InadequateHostsException(CrosDynamicSuiteException):
570 """Raised when there are too few hosts to run a suite."""
571 pass
572
573
574class NoHostsException(CrosDynamicSuiteException):
575 """Raised when there are no healthy hosts to run a suite."""
576 pass
577
578
579class ControlFileNotFound(CrosDynamicSuiteException):
580 """Raised when a control file cannot be found and/or read."""
581 pass
582
583
584class NoControlFileList(CrosDynamicSuiteException):
Chris Masone9807bd62012-07-11 14:44:17 -0700585 """Raised to indicate that a listing can't be done."""
586 pass
587
588
589class HostLockManagerReuse(CrosDynamicSuiteException):
590 """Raised when a caller tries to re-use a HostLockManager instance."""
Chris Masonef8b53062012-05-08 22:14:18 -0700591 pass
592
593
Simran Basi94d9bd02012-11-12 15:13:59 -0800594class ReimageAbortedException(CrosDynamicSuiteException):
595 """Raised when a Reimage job is aborted"""
596 pass
597
598
Alex Miller30837902013-02-02 15:52:43 -0800599class UnknownReimageType(CrosDynamicSuiteException):
600 """Raised when a suite passes in an invalid reimage type"""
601 pass
602
603
Simran Basi22aa9fe2012-12-07 16:37:09 -0800604class LabIsDownException(Exception):
605 """Raised when the Lab is Down"""
606 pass
607
608
Simran Basi41bfae42013-01-09 10:50:47 -0800609class BoardIsDisabledException(Exception):
610 """Raised when a certain board is disabled in the Lab"""
611 pass
612
613
Alex Miller24c27c12012-08-09 10:24:24 -0700614class NoUniquePackageFound(Exception):
615 """Raised when an executable cannot be mapped back to a single package."""
616 pass
617
618
mbligh91672252008-10-16 22:28:34 +0000619# This MUST remain at the end of the file.
620# Limit 'from error import *' to only import the exception instances.
621for _name, _thing in locals().items():
622 try:
623 if issubclass(_thing, Exception):
624 __all__.append(_name)
625 except TypeError:
626 pass # _thing not a class
627__all__ = tuple(__all__)