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