Home | History | Annotate | Download | only in common_lib
      1 #pylint: disable-msg=C0111
      2 
      3 """
      4 Internal global error types
      5 """
      6 
      7 import sys, traceback
      8 from 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 
     16 def 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 
     26 class TimeoutException(Exception):
     27     """Generic exception raised on retry timeouts."""
     28 
     29 
     30 class JobContinue(SystemExit):
     31     """Allow us to bail out requesting continuance."""
     32 
     33 
     34 class JobComplete(SystemExit):
     35     """Allow us to bail out indicating continuation not required."""
     36 
     37 
     38 class AutotestError(Exception):
     39     """The parent of all errors deliberatly thrown within the client code."""
     40 
     41 
     42 class JobError(AutotestError):
     43     """Indicates an error which terminates and fails the whole job (ABORT)."""
     44 
     45 
     46 class 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 
     61 class 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 
     67 class TestError(TestBaseException):
     68     """Indicates that something went wrong with the test harness itself."""
     69     exit_status = "ERROR"
     70 
     71 
     72 class 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 
     78 class TestFail(TestBaseException):
     79     """Indicates that the test failed, but the job will not continue."""
     80     exit_status = "FAIL"
     81 
     82 
     83 class TestWarn(TestBaseException):
     84     """Indicates that bad things (may) have happened, but not an explicit
     85     failure."""
     86     exit_status = "WARN"
     87 
     88 
     89 class 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 
     95 class 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 
    110 class 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 
    125 class 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 
    155 class CmdTimeoutError(CmdError):
    156     """Indicates that a command timed out."""
    157 
    158 
    159 class PackageError(TestError):
    160     """Indicates an error trying to perform a package operation."""
    161 
    162 
    163 class BarrierError(JobError):
    164     """Indicates an error happened during a barrier operation."""
    165 
    166 
    167 class BarrierAbortError(BarrierError):
    168     """Indicate that the barrier was explicitly aborted by a member."""
    169 
    170 
    171 class InstallError(JobError):
    172     """Indicates an installation error which Terminates and fails the job."""
    173 
    174 
    175 class AutotestRunError(AutotestError):
    176     """Indicates a problem running server side control files."""
    177 
    178 
    179 class 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 
    185 class 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 
    202 class HostInstallTimeoutError(JobError):
    203     """
    204     Indicates the machine failed to be installed after the predetermined
    205     timeout.
    206     """
    207 
    208 
    209 class AutotestHostRunError(GenericHostRunError, AutotestError):
    210     pass
    211 
    212 
    213 class 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 
    229 class 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 
    239 class AutoservError(Exception):
    240     pass
    241 
    242 
    243 class AutoservSSHTimeout(AutoservError):
    244     """SSH experienced a connection timeout"""
    245 
    246 
    247 class AutoservRunError(GenericHostRunError, AutoservError):
    248     pass
    249 
    250 
    251 class AutoservSshPermissionDeniedError(AutoservRunError):
    252     """Indicates that a SSH permission denied error was encountered."""
    253 
    254 
    255 class AutoservUnsupportedError(AutoservError):
    256     """Error raised when you try to use an unsupported optional feature"""
    257 
    258 
    259 class AutoservHostError(AutoservError):
    260     """Error reaching a host"""
    261 
    262 
    263 class AutoservHostIsShuttingDownError(AutoservHostError):
    264     """Host is shutting down"""
    265 
    266 
    267 class AutoservNotMountedHostError(AutoservHostError):
    268     """Found unmounted partitions that should be mounted"""
    269 
    270 
    271 class AutoservSshPingHostError(AutoservHostError):
    272     """SSH ping failed"""
    273 
    274 
    275 class 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 
    287 class 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 
    299 class AutoservHardwareHostError(AutoservHostError):
    300     """Found hardware problems with the host"""
    301 
    302 
    303 class AutoservRebootError(AutoservError):
    304     """Error occured while rebooting a machine"""
    305 
    306 
    307 class AutoservShutdownError(AutoservRebootError):
    308     """Error occured during shutdown of machine"""
    309 
    310 
    311 class AutoservSuspendError(AutoservRebootError):
    312     """Error occured while suspending a machine"""
    313 
    314 
    315 class 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 
    327 class AutoservRepairTotalFailure(AutoservError):
    328     """Raised if all attempts to repair the DUT failed."""
    329 
    330 
    331 class AutoservInstallError(AutoservError):
    332     """Error occured while installing autotest on a host"""
    333 
    334 
    335 class AutoservPidAlreadyDeadError(AutoservError):
    336     """Error occured by trying to kill a nonexistant PID"""
    337 
    338 
    339 # packaging system errors
    340 
    341 class PackagingError(AutotestError):
    342     'Abstract error class for all packaging related errors.'
    343 
    344 
    345 class PackageUploadError(PackagingError):
    346     'Raised when there is an error uploading the package'
    347 
    348 
    349 class PackageFetchError(PackagingError):
    350     'Raised when there is an error fetching the package'
    351 
    352 
    353 class PackageRemoveError(PackagingError):
    354     'Raised when there is an error removing the package'
    355 
    356 
    357 class PackageInstallError(PackagingError):
    358     'Raised when there is an error installing the package'
    359 
    360 
    361 class RepoDiskFullError(PackagingError):
    362     'Raised when the destination for packages is full'
    363 
    364 
    365 class RepoWriteError(PackagingError):
    366     "Raised when packager cannot write to a repo's desitnation"
    367 
    368 
    369 class RepoUnknownError(PackagingError):
    370     "Raised when packager cannot write to a repo's desitnation"
    371 
    372 
    373 class RepoError(PackagingError):
    374     "Raised when a repo isn't working in some way"
    375 
    376 
    377 class StageControlFileFailure(Exception):
    378     """Exceptions encountered staging control files."""
    379 
    380 
    381 class CrosDynamicSuiteException(Exception):
    382     """
    383     Base class for exceptions coming from dynamic suite code in
    384     server/cros/dynamic_suite/*.
    385     """
    386 
    387 
    388 class StageBuildFailure(CrosDynamicSuiteException):
    389     """Raised when the dev server throws 500 while staging a build."""
    390 
    391 
    392 class ControlFileEmpty(CrosDynamicSuiteException):
    393     """Raised when the control file exists on the server, but can't be read."""
    394 
    395 
    396 class ControlFileMalformed(CrosDynamicSuiteException):
    397     """Raised when an invalid control file is read."""
    398 
    399 
    400 class AsynchronousBuildFailure(CrosDynamicSuiteException):
    401     """Raised when the dev server throws 500 while finishing staging of a build.
    402     """
    403 
    404 
    405 class SuiteArgumentException(CrosDynamicSuiteException):
    406     """Raised when improper arguments are used to run a suite."""
    407 
    408 
    409 class MalformedDependenciesException(CrosDynamicSuiteException):
    410     """Raised when a build has a malformed dependency_info file."""
    411 
    412 
    413 class InadequateHostsException(CrosDynamicSuiteException):
    414     """Raised when there are too few hosts to run a suite."""
    415 
    416 
    417 class NoHostsException(CrosDynamicSuiteException):
    418     """Raised when there are no healthy hosts to run a suite."""
    419 
    420 
    421 class ControlFileNotFound(CrosDynamicSuiteException):
    422     """Raised when a control file cannot be found and/or read."""
    423 
    424 
    425 class NoControlFileList(CrosDynamicSuiteException):
    426     """Raised to indicate that a listing can't be done."""
    427 
    428 
    429 class SuiteControlFileException(CrosDynamicSuiteException):
    430     """Raised when failing to list the contents of all control file."""
    431 
    432 
    433 class HostLockManagerReuse(CrosDynamicSuiteException):
    434     """Raised when a caller tries to re-use a HostLockManager instance."""
    435 
    436 
    437 class ReimageAbortedException(CrosDynamicSuiteException):
    438     """Raised when a Reimage job is aborted"""
    439 
    440 
    441 class UnknownReimageType(CrosDynamicSuiteException):
    442     """Raised when a suite passes in an invalid reimage type"""
    443 
    444 
    445 class NoUniquePackageFound(Exception):
    446     """Raised when an executable cannot be mapped back to a single package."""
    447 
    448 
    449 class RPCException(Exception):
    450     """Raised when an RPC encounters an error that a client might wish to
    451     handle specially."""
    452 
    453 
    454 class NoEligibleHostException(RPCException):
    455     """Raised when no host could satisfy the requirements of a job."""
    456 
    457 
    458 class InvalidBgJobCall(Exception):
    459     """Raised when an invalid call is made to a BgJob object."""
    460 
    461 
    462 class HeartbeatOnlyAllowedInShardModeException(Exception):
    463     """Raised when a heartbeat is attempted but not allowed."""
    464 
    465 
    466 class UnallowedRecordsSentToMaster(Exception):
    467     """Raised when an illegal record was sent from shard to master."""
    468 
    469 
    470 class 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 
    480 class InvalidDataError(Exception):
    481     """Exception raised when invalid data provided for database operation."""
    482 
    483 
    484 class ContainerError(Exception):
    485     """Exception raised when program runs into error using container."""
    486 
    487 
    488 class 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.
    494 for _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