error.py revision c27c231ee840e8ce97012477ba1f917674375a1e
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 InstallError(JobError): 147 """Indicates an installation error which Terminates and fails the job.""" 148 pass 149 150 151class AutotestRunError(AutotestError): 152 """Indicates a problem running server side control files.""" 153 pass 154 155 156class AutotestTimeoutError(AutotestError): 157 """This exception is raised when an autotest test exceeds the timeout 158 parameter passed to run_timed_test and is killed. 159 """ 160 161 162# server-specific errors 163 164class AutoservError(Exception): 165 pass 166 167 168class AutoservSSHTimeout(AutoservError): 169 """SSH experienced a connection timeout""" 170 pass 171 172 173class AutoservRunError(AutoservError): 174 """\ 175 Errors raised by one of the run functions. Should always be 176 constructed with a tuple of two args (error description (str), 177 run result object). 178 """ 179 def __init__(self, description, result_obj): 180 self.description = description 181 self.result_obj = result_obj 182 AutoservError.__init__(self, description, result_obj) 183 184 def __str__(self): 185 return self.description + '\n' + repr(self.result_obj) 186 187 188class AutoservSshPermissionDeniedError(AutoservRunError): 189 """Indicates that a SSH permission denied error was encountered.""" 190 pass 191 192 193class AutoservVirtError(AutoservError): 194 """Vitualization related error""" 195 pass 196 197 198class AutoservUnsupportedError(AutoservError): 199 """Error raised when you try to use an unsupported optional feature""" 200 pass 201 202 203class AutoservHostError(AutoservError): 204 """Error reaching a host""" 205 pass 206 207 208class AutoservHostIsShuttingDownError(AutoservHostError): 209 """Host is shutting down""" 210 pass 211 212 213class AutoservNotMountedHostError(AutoservHostError): 214 """Found unmounted partitions that should be mounted""" 215 pass 216 217 218class AutoservSshPingHostError(AutoservHostError): 219 """SSH ping failed""" 220 pass 221 222 223class AutoservDiskFullHostError(AutoservHostError): 224 """Not enough free disk space on host""" 225 def __init__(self, path, want_gb, free_space_gb): 226 AutoservHostError.__init__(self, 227 'Not enough free space on %s - %.3fGB free, want %.3fGB' % 228 (path, free_space_gb, want_gb)) 229 230 self.path = path 231 self.want_gb = want_gb 232 self.free_space_gb = free_space_gb 233 234 235class AutoservHardwareHostError(AutoservHostError): 236 """Found hardware problems with the host""" 237 pass 238 239 240class AutoservRebootError(AutoservError): 241 """Error occured while rebooting a machine""" 242 pass 243 244 245class AutoservShutdownError(AutoservRebootError): 246 """Error occured during shutdown of machine""" 247 pass 248 249 250class AutoservSubcommandError(AutoservError): 251 """Indicates an error while executing a (forked) subcommand""" 252 def __init__(self, func, exit_code): 253 AutoservError.__init__(self, func, exit_code) 254 self.func = func 255 self.exit_code = exit_code 256 257 def __str__(self): 258 return ("Subcommand %s failed with exit code %d" % 259 (self.func, self.exit_code)) 260 261 262class AutoservHardwareRepairRequestedError(AutoservError): 263 """ 264 Exception class raised from Host.repair_full() (or overrides) when software 265 repair fails but it successfully managed to request a hardware repair (by 266 notifying the staff, sending mail, etc) 267 """ 268 pass 269 270 271# packaging system errors 272 273class PackagingError(AutotestError): 274 'Abstract error class for all packaging related errors.' 275 276 277class PackageUploadError(PackagingError): 278 'Raised when there is an error uploading the package' 279 280 281class PackageFetchError(PackagingError): 282 'Raised when there is an error fetching the package' 283 284 285class PackageRemoveError(PackagingError): 286 'Raised when there is an error removing the package' 287 288 289class PackageInstallError(PackagingError): 290 'Raised when there is an error installing the package' 291 292 293class RepoDiskFullError(PackagingError): 294 'Raised when the destination for packages is full' 295 296 297class RepoWriteError(PackagingError): 298 "Raised when packager cannot write to a repo's desitnation" 299 300 301class RepoUnknownError(PackagingError): 302 "Raised when packager cannot write to a repo's desitnation" 303 304 305class RepoError(PackagingError): 306 "Raised when a repo isn't working in some way" 307 308 309# This MUST remain at the end of the file. 310# Limit 'from error import *' to only import the exception instances. 311for _name, _thing in locals().items(): 312 try: 313 if issubclass(_thing, Exception): 314 __all__.append(_name) 315 except TypeError: 316 pass # _thing not a class 317__all__ = tuple(__all__) 318