error.py revision 999fb13dcbf4de5e37ca2b3059ef1061b5faba43
1""" 2Internal global error types 3""" 4 5import sys, traceback 6from traceback import format_exception 7 8# Add names you want to be imported by 'from errors import *' to this list. 9# This must be list not a tuple as we modify it to include all of our 10# the Exception classes we define below at the end of this file. 11__all__ = ['format_error'] 12 13 14def format_error(): 15 t, o, tb = sys.exc_info() 16 trace = format_exception(t, o, tb) 17 # Clear the backtrace to prevent a circular reference 18 # in the heap -- as per tutorial 19 tb = '' 20 21 return ''.join(trace) 22 23 24class JobContinue(SystemExit): 25 """Allow us to bail out requesting continuance.""" 26 pass 27 28 29class JobComplete(SystemExit): 30 """Allow us to bail out indicating continuation not required.""" 31 pass 32 33 34class AutotestError(Exception): 35 """The parent of all errors deliberatly thrown within the client code.""" 36 pass 37 38 39class JobError(AutotestError): 40 """Indicates an error which terminates and fails the whole job (ABORT).""" 41 pass 42 43 44class UnhandledJobError(JobError): 45 """Indicates an unhandled error in a job.""" 46 def __init__(self, unhandled_exception): 47 if isinstance(unhandled_exception, JobError): 48 JobError.__init__(self, *unhandled_exception.args) 49 else: 50 msg = "Unhandled %s: %s" 51 msg %= (unhandled_exception.__class__.__name__, 52 unhandled_exception) 53 msg += "\n" + traceback.format_exc() 54 JobError.__init__(self, msg) 55 56 57class TestBaseException(AutotestError): 58 """The parent of all test exceptions.""" 59 # Children are required to override this. Never instantiate directly. 60 exit_status="NEVER_RAISE_THIS" 61 62 63class TestError(TestBaseException): 64 """Indicates that something went wrong with the test harness itself.""" 65 exit_status="ERROR" 66 67 68class TestNAError(TestBaseException): 69 """Indictates that the test is Not Applicable. Should be thrown 70 when various conditions are such that the test is inappropriate.""" 71 exit_status="TEST_NA" 72 73 74class TestFail(TestBaseException): 75 """Indicates that the test failed, but the job will not continue.""" 76 exit_status="FAIL" 77 78 79class TestWarn(TestBaseException): 80 """Indicates that bad things (may) have happened, but not an explicit 81 failure.""" 82 exit_status="WARN" 83 84 85class UnhandledTestError(TestError): 86 """Indicates an unhandled error in a test.""" 87 def __init__(self, unhandled_exception): 88 if isinstance(unhandled_exception, TestError): 89 TestError.__init__(self, *unhandled_exception.args) 90 else: 91 msg = "Unhandled %s: %s" 92 msg %= (unhandled_exception.__class__.__name__, 93 unhandled_exception) 94 msg += "\n" + traceback.format_exc() 95 TestError.__init__(self, msg) 96 97 98class UnhandledTestFail(TestFail): 99 """Indicates an unhandled fail in a test.""" 100 def __init__(self, unhandled_exception): 101 if isinstance(unhandled_exception, TestFail): 102 TestFail.__init__(self, *unhandled_exception.args) 103 else: 104 msg = "Unhandled %s: %s" 105 msg %= (unhandled_exception.__class__.__name__, 106 unhandled_exception) 107 msg += "\n" + traceback.format_exc() 108 TestFail.__init__(self, msg) 109 110 111class CmdError(TestError): 112 """\ 113 Indicates that a command failed, is fatal to the test unless caught. 114 """ 115 def __init__(self, command, result_obj, additional_text=None): 116 TestError.__init__(self, command, result_obj, additional_text) 117 self.command = command 118 self.result_obj = result_obj 119 self.additional_text = additional_text 120 121 122 def __str__(self): 123 if self.result_obj.exit_status is None: 124 msg = "Command <%s> failed and is not responding to signals" 125 msg %= self.command 126 else: 127 msg = "Command <%s> failed, rc=%d" 128 msg %= (self.command, self.result_obj.exit_status) 129 130 if self.additional_text: 131 msg += ", " + self.additional_text 132 msg += '\n' + repr(self.result_obj) 133 return msg 134 135 136class PackageError(TestError): 137 """Indicates an error trying to perform a package operation.""" 138 pass 139 140 141class BarrierError(JobError): 142 """Indicates an error happened during a barrier operation.""" 143 pass 144 145 146class BarrierAbortError(BarrierError): 147 """Indicate that the barrier was explicitly aborted by a member.""" 148 pass 149 150 151class InstallError(JobError): 152 """Indicates an installation error which Terminates and fails the job.""" 153 pass 154 155 156class AutotestRunError(AutotestError): 157 """Indicates a problem running server side control files.""" 158 pass 159 160 161class AutotestTimeoutError(AutotestError): 162 """This exception is raised when an autotest test exceeds the timeout 163 parameter passed to run_timed_test and is killed. 164 """ 165 166 167class HostRunErrorMixIn(Exception): 168 """ 169 Indicates a problem in the host run() function raised from client code. 170 Should always be constructed with a tuple of two args (error description 171 (str), run result object). This is a common class mixed in to create the 172 client and server side versions of it. 173 """ 174 def __init__(self, description, result_obj): 175 self.description = description 176 self.result_obj = result_obj 177 Exception.__init__(self, description, result_obj) 178 179 def __str__(self): 180 return self.description + '\n' + repr(self.result_obj) 181 182 183class AutotestHostRunError(HostRunErrorMixIn, AutotestError): 184 pass 185 186 187# server-specific errors 188 189class AutoservError(Exception): 190 pass 191 192 193class AutoservSSHTimeout(AutoservError): 194 """SSH experienced a connection timeout""" 195 pass 196 197 198class AutoservRunError(HostRunErrorMixIn, AutoservError): 199 pass 200 201 202class AutoservSshPermissionDeniedError(AutoservRunError): 203 """Indicates that a SSH permission denied error was encountered.""" 204 pass 205 206 207class AutoservVirtError(AutoservError): 208 """Vitualization related error""" 209 pass 210 211 212class AutoservUnsupportedError(AutoservError): 213 """Error raised when you try to use an unsupported optional feature""" 214 pass 215 216 217class AutoservHostError(AutoservError): 218 """Error reaching a host""" 219 pass 220 221 222class AutoservHostIsShuttingDownError(AutoservHostError): 223 """Host is shutting down""" 224 pass 225 226 227class AutoservNotMountedHostError(AutoservHostError): 228 """Found unmounted partitions that should be mounted""" 229 pass 230 231 232class AutoservSshPingHostError(AutoservHostError): 233 """SSH ping failed""" 234 pass 235 236 237class AutoservDiskFullHostError(AutoservHostError): 238 """Not enough free disk space on host""" 239 def __init__(self, path, want_gb, free_space_gb): 240 AutoservHostError.__init__(self, 241 'Not enough free space on %s - %.3fGB free, want %.3fGB' % 242 (path, free_space_gb, want_gb)) 243 244 self.path = path 245 self.want_gb = want_gb 246 self.free_space_gb = free_space_gb 247 248 249class AutoservHardwareHostError(AutoservHostError): 250 """Found hardware problems with the host""" 251 pass 252 253 254class AutoservRebootError(AutoservError): 255 """Error occured while rebooting a machine""" 256 pass 257 258 259class AutoservShutdownError(AutoservRebootError): 260 """Error occured during shutdown of machine""" 261 pass 262 263 264class AutoservSubcommandError(AutoservError): 265 """Indicates an error while executing a (forked) subcommand""" 266 def __init__(self, func, exit_code): 267 AutoservError.__init__(self, func, exit_code) 268 self.func = func 269 self.exit_code = exit_code 270 271 def __str__(self): 272 return ("Subcommand %s failed with exit code %d" % 273 (self.func, self.exit_code)) 274 275 276class AutoservHardwareRepairRequestedError(AutoservError): 277 """ 278 Exception class raised from Host.repair_full() (or overrides) when software 279 repair fails but it successfully managed to request a hardware repair (by 280 notifying the staff, sending mail, etc) 281 """ 282 pass 283 284 285class AutoservInstallError(AutoservError): 286 """Error occured while installing autotest on a host""" 287 pass 288 289 290# packaging system errors 291 292class PackagingError(AutotestError): 293 'Abstract error class for all packaging related errors.' 294 295 296class PackageUploadError(PackagingError): 297 'Raised when there is an error uploading the package' 298 299 300class PackageFetchError(PackagingError): 301 'Raised when there is an error fetching the package' 302 303 304class PackageRemoveError(PackagingError): 305 'Raised when there is an error removing the package' 306 307 308class PackageInstallError(PackagingError): 309 'Raised when there is an error installing the package' 310 311 312class RepoDiskFullError(PackagingError): 313 'Raised when the destination for packages is full' 314 315 316class RepoWriteError(PackagingError): 317 "Raised when packager cannot write to a repo's desitnation" 318 319 320class RepoUnknownError(PackagingError): 321 "Raised when packager cannot write to a repo's desitnation" 322 323 324class RepoError(PackagingError): 325 "Raised when a repo isn't working in some way" 326 327 328# This MUST remain at the end of the file. 329# Limit 'from error import *' to only import the exception instances. 330for _name, _thing in locals().items(): 331 try: 332 if issubclass(_thing, Exception): 333 __all__.append(_name) 334 except TypeError: 335 pass # _thing not a class 336__all__ = tuple(__all__) 337