1# Lint as: python2, python3 2#pylint: disable-msg=C0111 3 4""" 5Internal global error types 6""" 7 8from __future__ import absolute_import 9from __future__ import division 10from __future__ import print_function 11 12import six 13 14import sys, traceback 15from traceback import format_exception 16 17# Add names you want to be imported by 'from errors import *' to this list. 18# This must be list not a tuple as we modify it to include all of our 19# the Exception classes we define below at the end of this file. 20__all__ = ['format_error'] 21 22 23def format_error(): 24 t, o, tb = sys.exc_info() 25 trace = format_exception(t, o, tb) 26 # Clear the backtrace to prevent a circular reference 27 # in the heap -- as per tutorial 28 tb = '' 29 30 return ''.join(trace) 31 32 33class TimeoutException(Exception): 34 """Generic exception raised on retry timeouts.""" 35 36 37class JobContinue(SystemExit): 38 """Allow us to bail out requesting continuance.""" 39 40 41class JobComplete(SystemExit): 42 """Allow us to bail out indicating continuation not required.""" 43 44 45class AutotestError(Exception): 46 """The parent of all errors deliberatly thrown within the client code.""" 47 48 49class JobError(AutotestError): 50 """Indicates an error which terminates and fails the whole job (ABORT).""" 51 52 53class UnhandledJobError(JobError): 54 """Indicates an unhandled error in a job.""" 55 def __init__(self, unhandled_exception): 56 if isinstance(unhandled_exception, JobError): 57 JobError.__init__(self, *unhandled_exception.args) 58 elif isinstance(unhandled_exception, six.string_types): 59 JobError.__init__(self, unhandled_exception) 60 else: 61 msg = "Unhandled %s: %s" 62 msg %= (unhandled_exception.__class__.__name__, 63 unhandled_exception) 64 msg += "\n" + traceback.format_exc() 65 JobError.__init__(self, msg) 66 67 68class TestBaseException(AutotestError): 69 """The parent of all test exceptions.""" 70 # Children are required to override this. Never instantiate directly. 71 exit_status = "NEVER_RAISE_THIS" 72 73 74class TestError(TestBaseException): 75 """Indicates that something went wrong with the test harness itself.""" 76 exit_status = "ERROR" 77 78 79class TestNAError(TestBaseException): 80 """Indictates that the test is Not Applicable. Should be thrown 81 when various conditions are such that the test is inappropriate.""" 82 exit_status = "TEST_NA" 83 84 85class TestFail(TestBaseException): 86 """Indicates that the test failed, but the job will not continue.""" 87 exit_status = "FAIL" 88 89 90class TestWarn(TestBaseException): 91 """Indicates that bad things (may) have happened, but not an explicit 92 failure.""" 93 exit_status = "WARN" 94 95 96class UnhandledTestError(TestError): 97 """Indicates an unhandled error in a test.""" 98 def __init__(self, unhandled_exception): 99 if isinstance(unhandled_exception, TestError): 100 TestError.__init__(self, *unhandled_exception.args) 101 elif isinstance(unhandled_exception, six.string_types): 102 TestError.__init__(self, unhandled_exception) 103 else: 104 msg = "Unhandled %s: %s" 105 msg %= (unhandled_exception.__class__.__name__, 106 unhandled_exception) 107 msg += "\n" + traceback.format_exc() 108 TestError.__init__(self, msg) 109 110 111class UnhandledTestFail(TestFail): 112 """Indicates an unhandled fail in a test.""" 113 def __init__(self, unhandled_exception): 114 if isinstance(unhandled_exception, TestFail): 115 TestFail.__init__(self, *unhandled_exception.args) 116 elif isinstance(unhandled_exception, six.string_types): 117 TestFail.__init__(self, unhandled_exception) 118 else: 119 msg = "Unhandled %s: %s" 120 msg %= (unhandled_exception.__class__.__name__, 121 unhandled_exception) 122 msg += "\n" + traceback.format_exc() 123 TestFail.__init__(self, msg) 124 125 126class CmdError(TestError): 127 """Indicates that a command failed, is fatal to the test unless caught. 128 129 @type command: str 130 @type result_obj: autotest_lib.client.common_lib.utils.CmdResult 131 @type additional_text: str | None 132 """ 133 def __init__(self, command, result_obj, additional_text=None): 134 TestError.__init__(self, command, result_obj, additional_text) 135 self.command = command 136 self.result_obj = result_obj 137 self.additional_text = additional_text 138 139 def __str__(self): 140 if self.result_obj.exit_status is None: 141 msg = "Command <%s> failed and is not responding to signals" 142 msg %= self.command 143 else: 144 msg = "Command <%s> failed, rc=%d" 145 msg %= (self.command, self.result_obj.exit_status) 146 147 if self.additional_text: 148 msg += ", " + self.additional_text 149 msg += '\n' + repr(self.result_obj) 150 return msg 151 152 def __eq__(self, other): 153 if type(self) == type(other): 154 return (self.command == other.command 155 and self.result_obj == other.result_obj 156 and self.additional_text == other.additional_text) 157 else: 158 return NotImplemented 159 160 161class CmdTimeoutError(CmdError): 162 """Indicates that a command timed out.""" 163 164 165class PackageError(TestError): 166 """Indicates an error trying to perform a package operation.""" 167 168 169class BarrierError(JobError): 170 """Indicates an error happened during a barrier operation.""" 171 172 173class BarrierAbortError(BarrierError): 174 """Indicate that the barrier was explicitly aborted by a member.""" 175 176 177class InstallError(JobError): 178 """Indicates an installation error which Terminates and fails the job.""" 179 180 181class AutotestRunError(AutotestError): 182 """Indicates a problem running server side control files.""" 183 184 185class AutotestTimeoutError(AutotestError): 186 """This exception is raised when an autotest test exceeds the timeout 187 parameter passed to run_timed_test and is killed. 188 """ 189 190 191class GenericHostRunError(Exception): 192 """Indicates a problem in the host run() function running in either client 193 or server code. 194 195 Should always be constructed with a tuple of two args (error description 196 (str), run result object). This is a common class used to create the client 197 and server side versions of it when the distinction is useful. 198 """ 199 def __init__(self, description, result_obj): 200 self.description = description 201 self.result_obj = result_obj 202 Exception.__init__(self, description, result_obj) 203 204 def __str__(self): 205 return self.description + '\n' + repr(self.result_obj) 206 207 208class HostInstallTimeoutError(JobError): 209 """ 210 Indicates the machine failed to be installed after the predetermined 211 timeout. 212 """ 213 214 215class AutotestHostRunError(GenericHostRunError, AutotestError): 216 pass 217 218 219class AutotestHostRunCmdError(AutotestHostRunError): 220 """Indicates that the command run via Host.run failed. 221 222 This is equivalent to CmdError when raised from a Host object instead of 223 directly on the DUT using utils.run 224 """ 225 226 def __init__(self, command, result_obj, additional_text=''): 227 description = command 228 if additional_text: 229 description += ' (%s)' % additional_text 230 super(AutotestHostRunCmdError, self).__init__(description, result_obj) 231 self.command = command 232 self.additional_text = additional_text 233 234 235class AutotestHostRunTimeoutError(AutotestHostRunCmdError): 236 """Indicates that a command run via Host.run timed out. 237 238 This is equivalent to CmdTimeoutError when raised from a Host object instead 239 of directly on the DUT using utils.run 240 """ 241 242 243# server-specific errors 244 245class AutoservError(Exception): 246 pass 247 248 249class AutoservSSHTimeout(AutoservError): 250 """SSH experienced a connection timeout""" 251 252 253class AutoservRunError(GenericHostRunError, AutoservError): 254 pass 255 256 257class AutoservSshPermissionDeniedError(AutoservRunError): 258 """Indicates that a SSH permission denied error was encountered.""" 259 260 261class AutoservUnsupportedError(AutoservError): 262 """Error raised when you try to use an unsupported optional feature""" 263 264 265class AutoservHostError(AutoservError): 266 """Error reaching a host""" 267 268 269class AutoservHostIsShuttingDownError(AutoservHostError): 270 """Host is shutting down""" 271 272 273class AutoservNotMountedHostError(AutoservHostError): 274 """Found unmounted partitions that should be mounted""" 275 276 277class AutoservSshPingHostError(AutoservHostError): 278 """SSH ping failed""" 279 280 281class AutoservDiskFullHostError(AutoservHostError): 282 """Not enough free disk space on host""" 283 284 def __init__(self, path, want_gb, free_space_gb): 285 super(AutoservDiskFullHostError, self).__init__( 286 'Not enough free space on %s - %.3fGB free, want %.3fGB' % 287 (path, free_space_gb, want_gb)) 288 self.path = path 289 self.want_gb = want_gb 290 self.free_space_gb = free_space_gb 291 292 293class AutoservNoFreeInodesError(AutoservHostError): 294 """Not enough free i-nodes on host""" 295 296 def __init__(self, path, want_inodes, free_inodes): 297 super(AutoservNoFreeInodesError, self).__init__( 298 'Not enough free inodes on %s - %d free, want %d' % 299 (path, free_inodes, want_inodes)) 300 self.path = path 301 self.want_inodes = want_inodes 302 self.free_inodes = free_inodes 303 304 305class AutoservHardwareHostError(AutoservHostError): 306 """Found hardware problems with the host""" 307 308 309class AutoservRebootError(AutoservError): 310 """Error occured while rebooting a machine""" 311 312 313class AutoservShutdownError(AutoservRebootError): 314 """Error occured during shutdown of machine""" 315 316 317class AutoservSuspendError(AutoservRebootError): 318 """Error occured while suspending a machine""" 319 320 321class AutoservSubcommandError(AutoservError): 322 """Indicates an error while executing a (forked) subcommand""" 323 def __init__(self, func, exit_code): 324 AutoservError.__init__(self, func, exit_code) 325 self.func = func 326 self.exit_code = exit_code 327 328 def __str__(self): 329 return ("Subcommand %s failed with exit code %d" % 330 (self.func, self.exit_code)) 331 332 333class AutoservRepairTotalFailure(AutoservError): 334 """Raised if all attempts to repair the DUT failed.""" 335 336 337class AutoservInstallError(AutoservError): 338 """Error occured while installing autotest on a host""" 339 340 341class AutoservPidAlreadyDeadError(AutoservError): 342 """Error occured by trying to kill a nonexistant PID""" 343 344 345# packaging system errors 346 347class PackagingError(AutotestError): 348 'Abstract error class for all packaging related errors.' 349 350 351class PackageUploadError(PackagingError): 352 'Raised when there is an error uploading the package' 353 354 355class PackageFetchError(PackagingError): 356 'Raised when there is an error fetching the package' 357 358 359class PackageRemoveError(PackagingError): 360 'Raised when there is an error removing the package' 361 362 363class PackageInstallError(PackagingError): 364 'Raised when there is an error installing the package' 365 366 367class RepoDiskFullError(PackagingError): 368 'Raised when the destination for packages is full' 369 370 371class RepoWriteError(PackagingError): 372 "Raised when packager cannot write to a repo's desitnation" 373 374 375class RepoUnknownError(PackagingError): 376 "Raised when packager cannot write to a repo's desitnation" 377 378 379class RepoError(PackagingError): 380 "Raised when a repo isn't working in some way" 381 382 383class StageControlFileFailure(Exception): 384 """Exceptions encountered staging control files.""" 385 386 387class CrosDynamicSuiteException(Exception): 388 """ 389 Base class for exceptions coming from dynamic suite code in 390 server/cros/dynamic_suite/*. 391 """ 392 393 394class StageBuildFailure(CrosDynamicSuiteException): 395 """Raised when the dev server throws 500 while staging a build.""" 396 397 398class ControlFileEmpty(CrosDynamicSuiteException): 399 """Raised when the control file exists on the server, but can't be read.""" 400 401 402class ControlFileMalformed(CrosDynamicSuiteException): 403 """Raised when an invalid control file is read.""" 404 405 406class AsynchronousBuildFailure(CrosDynamicSuiteException): 407 """Raised when the dev server throws 500 while finishing staging of a build. 408 """ 409 410 411class SuiteArgumentException(CrosDynamicSuiteException): 412 """Raised when improper arguments are used to run a suite.""" 413 414 415class MalformedDependenciesException(CrosDynamicSuiteException): 416 """Raised when a build has a malformed dependency_info file.""" 417 418 419class InadequateHostsException(CrosDynamicSuiteException): 420 """Raised when there are too few hosts to run a suite.""" 421 422 423class NoHostsException(CrosDynamicSuiteException): 424 """Raised when there are no healthy hosts to run a suite.""" 425 426 427class ControlFileNotFound(CrosDynamicSuiteException): 428 """Raised when a control file cannot be found and/or read.""" 429 430 431class NoControlFileList(CrosDynamicSuiteException): 432 """Raised to indicate that a listing can't be done.""" 433 434 435class SuiteControlFileException(CrosDynamicSuiteException): 436 """Raised when failing to list the contents of all control file.""" 437 438 439class HostLockManagerReuse(CrosDynamicSuiteException): 440 """Raised when a caller tries to re-use a HostLockManager instance.""" 441 442 443class ReimageAbortedException(CrosDynamicSuiteException): 444 """Raised when a Reimage job is aborted""" 445 446 447class UnknownReimageType(CrosDynamicSuiteException): 448 """Raised when a suite passes in an invalid reimage type""" 449 450 451class NoUniquePackageFound(Exception): 452 """Raised when an executable cannot be mapped back to a single package.""" 453 454 455class RPCException(Exception): 456 """Raised when an RPC encounters an error that a client might wish to 457 handle specially.""" 458 459 460class NoEligibleHostException(RPCException): 461 """Raised when no host could satisfy the requirements of a job.""" 462 463 464class UnmodifiableLabelException(RPCException): 465 """Raised when an RPC tries to modify static labels.""" 466 467 468class UnmodifiableAttributeException(RPCException): 469 """Raised when an RPC tries to modify static attributes.""" 470 471 472class InvalidBgJobCall(Exception): 473 """Raised when an invalid call is made to a BgJob object.""" 474 475 476class HeartbeatOnlyAllowedInShardModeException(Exception): 477 """Raised when a heartbeat is attempted but not allowed.""" 478 479 480class UnallowedRecordsSentToMain(Exception): 481 """Raised when an illegal record was sent from shard to main.""" 482 483 484class IgnorableUnallowedRecordsSentToMain(UnallowedRecordsSentToMain): 485 """Raised when non-fatal illegal record was sent from shard. 486 487 This exception may be raised by rpc model logic on main, but will 488 not be returned back to heartbeat client. It indicates that some records 489 may have been illegal, but the main is ignoring those records and 490 proceeding with the rest of the heartbeat handling. 491 """ 492 493 494class InvalidDataError(Exception): 495 """Exception raised when invalid data provided for database operation.""" 496 497 498class ContainerError(Exception): 499 """Exception raised when program runs into error using container.""" 500 501 502class IllegalUser(Exception): 503 """Exception raise when a program runs as an illegal user.""" 504 505 506class AutoservDirectoryNotFoundError(AutoservHostError): 507 """Exception raised when an expected directory is not found.""" 508 509 510class AutoservDiskSizeUnknownError(AutoservHostError): 511 """Exception raised when the disk space could not be determined.""" 512 513 514# This MUST remain at the end of the file. 515# Limit 'from error import *' to only import the exception instances. 516for _name, _thing in list(locals().items()): 517 try: 518 if issubclass(_thing, Exception): 519 __all__.append(_name) 520 except TypeError: 521 pass # _thing not a class 522__all__ = tuple(__all__) 523