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