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