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