blob: a6333754a4b832e0bad3a4df0dd908d101d9d011 [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
mbligh906b9f72007-11-29 18:56:17 +0000162class JobContinue(SystemExit):
jadmanski0afbb632008-06-06 21:10:57 +0000163 """Allow us to bail out requesting continuance."""
164 pass
mbligh906b9f72007-11-29 18:56:17 +0000165
mbligh7e1b1502008-06-06 15:05:41 +0000166
mbligh906b9f72007-11-29 18:56:17 +0000167class JobComplete(SystemExit):
jadmanski0afbb632008-06-06 21:10:57 +0000168 """Allow us to bail out indicating continuation not required."""
169 pass
mbligh906b9f72007-11-29 18:56:17 +0000170
mbligh7e1b1502008-06-06 15:05:41 +0000171
mbligh906b9f72007-11-29 18:56:17 +0000172class AutotestError(Exception):
jadmanski0afbb632008-06-06 21:10:57 +0000173 """The parent of all errors deliberatly thrown within the client code."""
Eric Li861b2d52011-02-04 14:50:35 -0800174 def __str__(self):
175 return Exception.__str__(self) + _context_message(self)
mbligh906b9f72007-11-29 18:56:17 +0000176
mbligh7e1b1502008-06-06 15:05:41 +0000177
mbligh906b9f72007-11-29 18:56:17 +0000178class JobError(AutotestError):
mbligh4f407462008-12-03 15:22:39 +0000179 """Indicates an error which terminates and fails the whole job (ABORT)."""
jadmanski0afbb632008-06-06 21:10:57 +0000180 pass
mbligh906b9f72007-11-29 18:56:17 +0000181
mbligh7e1b1502008-06-06 15:05:41 +0000182
mbligh4f407462008-12-03 15:22:39 +0000183class UnhandledJobError(JobError):
184 """Indicates an unhandled error in a job."""
185 def __init__(self, unhandled_exception):
186 if isinstance(unhandled_exception, JobError):
mbligh1ca1c2c2008-12-09 23:38:25 +0000187 JobError.__init__(self, *unhandled_exception.args)
Eric Li861b2d52011-02-04 14:50:35 -0800188 elif isinstance(unhandled_exception, str):
189 JobError.__init__(self, unhandled_exception)
mbligh4f407462008-12-03 15:22:39 +0000190 else:
191 msg = "Unhandled %s: %s"
192 msg %= (unhandled_exception.__class__.__name__,
193 unhandled_exception)
Eric Li861b2d52011-02-04 14:50:35 -0800194 if not isinstance(unhandled_exception, AutotestError):
195 msg += _context_message(unhandled_exception)
mbligh4f407462008-12-03 15:22:39 +0000196 msg += "\n" + traceback.format_exc()
197 JobError.__init__(self, msg)
198
199
mblighc2180832008-07-25 03:26:12 +0000200class TestBaseException(AutotestError):
201 """The parent of all test exceptions."""
mbligh021679f2008-11-27 00:43:19 +0000202 # Children are required to override this. Never instantiate directly.
Alex Miller30837902013-02-02 15:52:43 -0800203 exit_status = "NEVER_RAISE_THIS"
mblighc2180832008-07-25 03:26:12 +0000204
205
206class TestError(TestBaseException):
mblighb48fa562008-06-23 17:29:40 +0000207 """Indicates that something went wrong with the test harness itself."""
Alex Miller30837902013-02-02 15:52:43 -0800208 exit_status = "ERROR"
mblighb48fa562008-06-23 17:29:40 +0000209
jadmanski8d01bfe2008-06-23 18:13:24 +0000210
mblighc2180832008-07-25 03:26:12 +0000211class TestNAError(TestBaseException):
jadmanski0afbb632008-06-06 21:10:57 +0000212 """Indictates that the test is Not Applicable. Should be thrown
mblighb48fa562008-06-23 17:29:40 +0000213 when various conditions are such that the test is inappropriate."""
Alex Miller30837902013-02-02 15:52:43 -0800214 exit_status = "TEST_NA"
mblighb48fa562008-06-23 17:29:40 +0000215
jadmanski8d01bfe2008-06-23 18:13:24 +0000216
mblighc2180832008-07-25 03:26:12 +0000217class TestFail(TestBaseException):
mblighb48fa562008-06-23 17:29:40 +0000218 """Indicates that the test failed, but the job will not continue."""
Alex Miller30837902013-02-02 15:52:43 -0800219 exit_status = "FAIL"
mblighb48fa562008-06-23 17:29:40 +0000220
jadmanski8d01bfe2008-06-23 18:13:24 +0000221
mblighc2180832008-07-25 03:26:12 +0000222class TestWarn(TestBaseException):
mblighb48fa562008-06-23 17:29:40 +0000223 """Indicates that bad things (may) have happened, but not an explicit
224 failure."""
Alex Miller30837902013-02-02 15:52:43 -0800225 exit_status = "WARN"
mbligh6a2a2df2008-01-16 17:41:55 +0000226
mbligh7e1b1502008-06-06 15:05:41 +0000227
Aviv Keshet39164ca2013-03-27 15:08:33 -0700228class TestFailRetry(TestFail):
229 """Indicates that the test failed, but in a manner that may be retried
230 if test retries are enabled for this test."""
231 exit_status = "FAIL"
232
233
mblighc2180832008-07-25 03:26:12 +0000234class UnhandledTestError(TestError):
235 """Indicates an unhandled error in a test."""
236 def __init__(self, unhandled_exception):
237 if isinstance(unhandled_exception, TestError):
238 TestError.__init__(self, *unhandled_exception.args)
Eric Li861b2d52011-02-04 14:50:35 -0800239 elif isinstance(unhandled_exception, str):
240 TestError.__init__(self, unhandled_exception)
mblighc2180832008-07-25 03:26:12 +0000241 else:
242 msg = "Unhandled %s: %s"
243 msg %= (unhandled_exception.__class__.__name__,
244 unhandled_exception)
Eric Li861b2d52011-02-04 14:50:35 -0800245 if not isinstance(unhandled_exception, AutotestError):
246 msg += _context_message(unhandled_exception)
mblighc2180832008-07-25 03:26:12 +0000247 msg += "\n" + traceback.format_exc()
248 TestError.__init__(self, msg)
249
250
251class UnhandledTestFail(TestFail):
252 """Indicates an unhandled fail in a test."""
253 def __init__(self, unhandled_exception):
254 if isinstance(unhandled_exception, TestFail):
255 TestFail.__init__(self, *unhandled_exception.args)
Eric Li861b2d52011-02-04 14:50:35 -0800256 elif isinstance(unhandled_exception, str):
257 TestFail.__init__(self, unhandled_exception)
mblighc2180832008-07-25 03:26:12 +0000258 else:
259 msg = "Unhandled %s: %s"
260 msg %= (unhandled_exception.__class__.__name__,
261 unhandled_exception)
Eric Li861b2d52011-02-04 14:50:35 -0800262 if not isinstance(unhandled_exception, AutotestError):
263 msg += _context_message(unhandled_exception)
mblighc2180832008-07-25 03:26:12 +0000264 msg += "\n" + traceback.format_exc()
265 TestFail.__init__(self, msg)
266
267
mbligh906b9f72007-11-29 18:56:17 +0000268class CmdError(TestError):
jadmanski0afbb632008-06-06 21:10:57 +0000269 """\
270 Indicates that a command failed, is fatal to the test unless caught.
271 """
272 def __init__(self, command, result_obj, additional_text=None):
273 TestError.__init__(self, command, result_obj, additional_text)
mblighc23051c2008-06-27 19:26:46 +0000274 self.command = command
275 self.result_obj = result_obj
276 self.additional_text = additional_text
mbligh6a2a2df2008-01-16 17:41:55 +0000277
jadmanski0afbb632008-06-06 21:10:57 +0000278 def __str__(self):
jadmanski6ef0b672008-09-30 22:50:19 +0000279 if self.result_obj.exit_status is None:
280 msg = "Command <%s> failed and is not responding to signals"
281 msg %= self.command
282 else:
283 msg = "Command <%s> failed, rc=%d"
284 msg %= (self.command, self.result_obj.exit_status)
285
mblighc23051c2008-06-27 19:26:46 +0000286 if self.additional_text:
287 msg += ", " + self.additional_text
Eric Li861b2d52011-02-04 14:50:35 -0800288 msg += _context_message(self)
showard6d7e94f2008-08-20 20:53:34 +0000289 msg += '\n' + repr(self.result_obj)
jadmanski0afbb632008-06-06 21:10:57 +0000290 return msg
mbligh906b9f72007-11-29 18:56:17 +0000291
mbligh7e1b1502008-06-06 15:05:41 +0000292
mbligh906b9f72007-11-29 18:56:17 +0000293class PackageError(TestError):
jadmanski0afbb632008-06-06 21:10:57 +0000294 """Indicates an error trying to perform a package operation."""
295 pass
mbligh906b9f72007-11-29 18:56:17 +0000296
mbligh7e1b1502008-06-06 15:05:41 +0000297
mblighe8673102008-07-16 14:09:03 +0000298class BarrierError(JobError):
299 """Indicates an error happened during a barrier operation."""
300 pass
301
302
mbligh999fb132010-04-23 17:22:03 +0000303class BarrierAbortError(BarrierError):
304 """Indicate that the barrier was explicitly aborted by a member."""
305 pass
306
307
mbligh5deff3d2008-01-04 21:21:28 +0000308class InstallError(JobError):
jadmanski0afbb632008-06-06 21:10:57 +0000309 """Indicates an installation error which Terminates and fails the job."""
310 pass
mbligh03f4fc72007-11-29 20:56:14 +0000311
mbligh7e1b1502008-06-06 15:05:41 +0000312
mbligh6f015c42008-02-12 20:55:03 +0000313class AutotestRunError(AutotestError):
mbligh021679f2008-11-27 00:43:19 +0000314 """Indicates a problem running server side control files."""
jadmanski0afbb632008-06-06 21:10:57 +0000315 pass
mbligh6f015c42008-02-12 20:55:03 +0000316
mbligh7e1b1502008-06-06 15:05:41 +0000317
mbligh6f015c42008-02-12 20:55:03 +0000318class AutotestTimeoutError(AutotestError):
jadmanski0afbb632008-06-06 21:10:57 +0000319 """This exception is raised when an autotest test exceeds the timeout
320 parameter passed to run_timed_test and is killed.
321 """
Dale Curtis8adf7892011-09-08 16:13:36 -0700322 pass
mbligh6f015c42008-02-12 20:55:03 +0000323
324
mblighce955fc2009-08-24 21:59:02 +0000325class HostRunErrorMixIn(Exception):
326 """
327 Indicates a problem in the host run() function raised from client code.
328 Should always be constructed with a tuple of two args (error description
329 (str), run result object). This is a common class mixed in to create the
330 client and server side versions of it.
331 """
332 def __init__(self, description, result_obj):
333 self.description = description
334 self.result_obj = result_obj
335 Exception.__init__(self, description, result_obj)
336
337 def __str__(self):
338 return self.description + '\n' + repr(self.result_obj)
339
340
Dale Curtis8adf7892011-09-08 16:13:36 -0700341class HostInstallTimeoutError(JobError):
342 """
343 Indicates the machine failed to be installed after the predetermined
344 timeout.
345 """
346 pass
347
348
mblighce955fc2009-08-24 21:59:02 +0000349class AutotestHostRunError(HostRunErrorMixIn, AutotestError):
350 pass
351
352
mbligh03f4fc72007-11-29 20:56:14 +0000353# server-specific errors
354
355class AutoservError(Exception):
jadmanski0afbb632008-06-06 21:10:57 +0000356 pass
mbligh03f4fc72007-11-29 20:56:14 +0000357
358
mbligh34faa282008-01-16 17:44:49 +0000359class AutoservSSHTimeout(AutoservError):
jadmanski0afbb632008-06-06 21:10:57 +0000360 """SSH experienced a connection timeout"""
361 pass
mbligh34faa282008-01-16 17:44:49 +0000362
363
mblighce955fc2009-08-24 21:59:02 +0000364class AutoservRunError(HostRunErrorMixIn, AutoservError):
365 pass
showard6d7e94f2008-08-20 20:53:34 +0000366
mbligh03f4fc72007-11-29 20:56:14 +0000367
mbligh9d738d62009-03-09 21:17:10 +0000368class AutoservSshPermissionDeniedError(AutoservRunError):
369 """Indicates that a SSH permission denied error was encountered."""
370 pass
371
372
mbligh03f4fc72007-11-29 20:56:14 +0000373class AutoservVirtError(AutoservError):
jadmanski0afbb632008-06-06 21:10:57 +0000374 """Vitualization related error"""
375 pass
mbligh03f4fc72007-11-29 20:56:14 +0000376
377
378class AutoservUnsupportedError(AutoservError):
jadmanski0afbb632008-06-06 21:10:57 +0000379 """Error raised when you try to use an unsupported optional feature"""
380 pass
mbligh03f4fc72007-11-29 20:56:14 +0000381
mbligh7e1b1502008-06-06 15:05:41 +0000382
mbligh03f4fc72007-11-29 20:56:14 +0000383class AutoservHostError(AutoservError):
jadmanski0afbb632008-06-06 21:10:57 +0000384 """Error reaching a host"""
385 pass
mbligh03f4fc72007-11-29 20:56:14 +0000386
mbligh7e1b1502008-06-06 15:05:41 +0000387
mblighc971c5f2009-06-08 16:48:54 +0000388class AutoservHostIsShuttingDownError(AutoservHostError):
389 """Host is shutting down"""
390 pass
391
392
393class AutoservNotMountedHostError(AutoservHostError):
394 """Found unmounted partitions that should be mounted"""
395 pass
396
397
398class AutoservSshPingHostError(AutoservHostError):
399 """SSH ping failed"""
400 pass
401
402
403class AutoservDiskFullHostError(AutoservHostError):
404 """Not enough free disk space on host"""
405 def __init__(self, path, want_gb, free_space_gb):
406 AutoservHostError.__init__(self,
407 'Not enough free space on %s - %.3fGB free, want %.3fGB' %
408 (path, free_space_gb, want_gb))
409
410 self.path = path
411 self.want_gb = want_gb
412 self.free_space_gb = free_space_gb
413
414
415class AutoservHardwareHostError(AutoservHostError):
416 """Found hardware problems with the host"""
417 pass
418
419
mbligh03f4fc72007-11-29 20:56:14 +0000420class AutoservRebootError(AutoservError):
jadmanski0afbb632008-06-06 21:10:57 +0000421 """Error occured while rebooting a machine"""
422 pass
mbligh6e2ffec2008-03-05 16:08:34 +0000423
mbligh7e1b1502008-06-06 15:05:41 +0000424
jadmanski65eb8f52009-07-24 18:34:43 +0000425class AutoservShutdownError(AutoservRebootError):
426 """Error occured during shutdown of machine"""
427 pass
428
429
mbligh6e2ffec2008-03-05 16:08:34 +0000430class AutoservSubcommandError(AutoservError):
jadmanski0afbb632008-06-06 21:10:57 +0000431 """Indicates an error while executing a (forked) subcommand"""
432 def __init__(self, func, exit_code):
433 AutoservError.__init__(self, func, exit_code)
434 self.func = func
435 self.exit_code = exit_code
mbligh7e1b1502008-06-06 15:05:41 +0000436
jadmanski0afbb632008-06-06 21:10:57 +0000437 def __str__(self):
438 return ("Subcommand %s failed with exit code %d" %
439 (self.func, self.exit_code))
mbligh91672252008-10-16 22:28:34 +0000440
441
Scott Zawalski62bacae2013-03-05 10:40:32 -0500442class AutoservRepairTotalFailure(AutoservError):
443 """Raised if all attempts to repair the DUT failed."""
444 pass
445
446
447class AutoservRepairFailure(AutoservError):
448 """Raised by a repair method if it is unable to repair a DUT."""
449 pass
450
451
452class AutoservRepairMethodNA(AutoservError):
453 """Raised when for any reason a praticular repair method is NA."""
454 pass
455
456
mbligh25c0b8c2009-01-24 01:44:17 +0000457class AutoservHardwareRepairRequestedError(AutoservError):
458 """
459 Exception class raised from Host.repair_full() (or overrides) when software
460 repair fails but it successfully managed to request a hardware repair (by
461 notifying the staff, sending mail, etc)
462 """
463 pass
464
465
jadmanski2615f4a2010-07-19 16:39:56 +0000466class AutoservHardwareRepairRequiredError(AutoservError):
467 """
468 Exception class raised during repairs to indicate that a hardware repair
469 is going to be necessary.
470 """
471 pass
472
473
jadmanskic1dda212009-11-18 19:22:00 +0000474class AutoservInstallError(AutoservError):
475 """Error occured while installing autotest on a host"""
476 pass
477
478
Simran Basi31cf2bd2012-08-14 16:51:54 -0700479class AutoservPidAlreadyDeadError(AutoservError):
480 """Error occured by trying to kill a nonexistant PID"""
481 pass
482
483
jadmanskic27c2312009-08-05 20:58:51 +0000484# packaging system errors
485
486class PackagingError(AutotestError):
487 'Abstract error class for all packaging related errors.'
488
489
490class PackageUploadError(PackagingError):
491 'Raised when there is an error uploading the package'
492
493
494class PackageFetchError(PackagingError):
495 'Raised when there is an error fetching the package'
496
497
498class PackageRemoveError(PackagingError):
499 'Raised when there is an error removing the package'
500
501
502class PackageInstallError(PackagingError):
503 'Raised when there is an error installing the package'
504
505
506class RepoDiskFullError(PackagingError):
507 'Raised when the destination for packages is full'
508
509
510class RepoWriteError(PackagingError):
511 "Raised when packager cannot write to a repo's desitnation"
512
513
514class RepoUnknownError(PackagingError):
515 "Raised when packager cannot write to a repo's desitnation"
516
517
518class RepoError(PackagingError):
519 "Raised when a repo isn't working in some way"
520
521
Chris Masonef8b53062012-05-08 22:14:18 -0700522class CrosDynamicSuiteException(Exception):
523 """
Chris Masoneb4935552012-08-14 12:05:54 -0700524 Base class for exceptions coming from dynamic suite code in
525 server/cros/dynamic_suite/*.
Chris Masonef8b53062012-05-08 22:14:18 -0700526 """
527 pass
528
529
530class StageBuildFailure(CrosDynamicSuiteException):
531 """Raised when the dev server throws 500 while staging a build."""
532 pass
533
534
535class ControlFileEmpty(CrosDynamicSuiteException):
536 """Raised when the control file exists on the server, but can't be read."""
537 pass
538
539
Alex Millera713e252013-03-01 10:45:44 -0800540class ControlFileMalformed(CrosDynamicSuiteException):
541 """Raised when an invalid control file is read."""
542 pass
543
544
Chris Masonef8b53062012-05-08 22:14:18 -0700545class AsynchronousBuildFailure(CrosDynamicSuiteException):
546 """Raised when the dev server throws 500 while finishing staging of a build.
547 """
548 pass
549
550
551class SuiteArgumentException(CrosDynamicSuiteException):
552 """Raised when improper arguments are used to run a suite."""
553 pass
554
555
Chris Masone8906ab12012-07-23 15:37:56 -0700556class MalformedDependenciesException(CrosDynamicSuiteException):
557 """Raised when a build has a malformed dependency_info file."""
558 pass
559
560
Chris Masonef8b53062012-05-08 22:14:18 -0700561class InadequateHostsException(CrosDynamicSuiteException):
562 """Raised when there are too few hosts to run a suite."""
563 pass
564
565
566class NoHostsException(CrosDynamicSuiteException):
567 """Raised when there are no healthy hosts to run a suite."""
568 pass
569
570
571class ControlFileNotFound(CrosDynamicSuiteException):
572 """Raised when a control file cannot be found and/or read."""
573 pass
574
575
576class NoControlFileList(CrosDynamicSuiteException):
Chris Masone9807bd62012-07-11 14:44:17 -0700577 """Raised to indicate that a listing can't be done."""
578 pass
579
580
581class HostLockManagerReuse(CrosDynamicSuiteException):
582 """Raised when a caller tries to re-use a HostLockManager instance."""
Chris Masonef8b53062012-05-08 22:14:18 -0700583 pass
584
585
Simran Basi94d9bd02012-11-12 15:13:59 -0800586class ReimageAbortedException(CrosDynamicSuiteException):
587 """Raised when a Reimage job is aborted"""
588 pass
589
590
Alex Miller30837902013-02-02 15:52:43 -0800591class UnknownReimageType(CrosDynamicSuiteException):
592 """Raised when a suite passes in an invalid reimage type"""
593 pass
594
595
Simran Basi22aa9fe2012-12-07 16:37:09 -0800596class LabIsDownException(Exception):
597 """Raised when the Lab is Down"""
598 pass
599
600
Simran Basi41bfae42013-01-09 10:50:47 -0800601class BoardIsDisabledException(Exception):
602 """Raised when a certain board is disabled in the Lab"""
603 pass
604
605
Alex Miller24c27c12012-08-09 10:24:24 -0700606class NoUniquePackageFound(Exception):
607 """Raised when an executable cannot be mapped back to a single package."""
608 pass
609
610
mbligh91672252008-10-16 22:28:34 +0000611# This MUST remain at the end of the file.
612# Limit 'from error import *' to only import the exception instances.
613for _name, _thing in locals().items():
614 try:
615 if issubclass(_thing, Exception):
616 __all__.append(_name)
617 except TypeError:
618 pass # _thing not a class
619__all__ = tuple(__all__)