1# SPDX-License-Identifier: BSD-3-Clause 2# Copyright(c) 2010-2014 Intel Corporation 3# Copyright(c) 2022-2023 PANTHEON.tech s.r.o. 4# Copyright(c) 2022-2023 University of New Hampshire 5 6""" 7User-defined exceptions used across the framework. 8""" 9 10from enum import IntEnum, unique 11from typing import ClassVar 12 13 14@unique 15class ErrorSeverity(IntEnum): 16 """ 17 The severity of errors that occur during DTS execution. 18 All exceptions are caught and the most severe error is used as return code. 19 """ 20 21 NO_ERR = 0 22 GENERIC_ERR = 1 23 CONFIG_ERR = 2 24 REMOTE_CMD_EXEC_ERR = 3 25 SSH_ERR = 4 26 DPDK_BUILD_ERR = 10 27 TESTCASE_VERIFY_ERR = 20 28 BLOCKING_TESTSUITE_ERR = 25 29 30 31class DTSError(Exception): 32 """ 33 The base exception from which all DTS exceptions are derived. 34 Stores error severity. 35 """ 36 37 severity: ClassVar[ErrorSeverity] = ErrorSeverity.GENERIC_ERR 38 39 40class SSHTimeoutError(DTSError): 41 """ 42 Command execution timeout. 43 """ 44 45 command: str 46 output: str 47 severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR 48 49 def __init__(self, command: str, output: str): 50 self.command = command 51 self.output = output 52 53 def __str__(self) -> str: 54 return f"TIMEOUT on {self.command}" 55 56 def get_output(self) -> str: 57 return self.output 58 59 60class SSHConnectionError(DTSError): 61 """ 62 SSH connection error. 63 """ 64 65 host: str 66 errors: list[str] 67 severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR 68 69 def __init__(self, host: str, errors: list[str] | None = None): 70 self.host = host 71 self.errors = [] if errors is None else errors 72 73 def __str__(self) -> str: 74 message = f"Error trying to connect with {self.host}." 75 if self.errors: 76 message += f" Errors encountered while retrying: {', '.join(self.errors)}" 77 78 return message 79 80 81class SSHSessionDeadError(DTSError): 82 """ 83 SSH session is not alive. 84 It can no longer be used. 85 """ 86 87 host: str 88 severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR 89 90 def __init__(self, host: str): 91 self.host = host 92 93 def __str__(self) -> str: 94 return f"SSH session with {self.host} has died" 95 96 97class ConfigurationError(DTSError): 98 """ 99 Raised when an invalid configuration is encountered. 100 """ 101 102 severity: ClassVar[ErrorSeverity] = ErrorSeverity.CONFIG_ERR 103 104 105class RemoteCommandExecutionError(DTSError): 106 """ 107 Raised when a command executed on a Node returns a non-zero exit status. 108 """ 109 110 command: str 111 command_return_code: int 112 severity: ClassVar[ErrorSeverity] = ErrorSeverity.REMOTE_CMD_EXEC_ERR 113 114 def __init__(self, command: str, command_return_code: int): 115 self.command = command 116 self.command_return_code = command_return_code 117 118 def __str__(self) -> str: 119 return ( 120 f"Command {self.command} returned a non-zero exit code: " 121 f"{self.command_return_code}" 122 ) 123 124 125class RemoteDirectoryExistsError(DTSError): 126 """ 127 Raised when a remote directory to be created already exists. 128 """ 129 130 severity: ClassVar[ErrorSeverity] = ErrorSeverity.REMOTE_CMD_EXEC_ERR 131 132 133class DPDKBuildError(DTSError): 134 """ 135 Raised when DPDK build fails for any reason. 136 """ 137 138 severity: ClassVar[ErrorSeverity] = ErrorSeverity.DPDK_BUILD_ERR 139 140 141class TestCaseVerifyError(DTSError): 142 """ 143 Used in test cases to verify the expected behavior. 144 """ 145 146 value: str 147 severity: ClassVar[ErrorSeverity] = ErrorSeverity.TESTCASE_VERIFY_ERR 148 149 def __init__(self, value: str): 150 self.value = value 151 152 def __str__(self) -> str: 153 return repr(self.value) 154 155 156class BlockingTestSuiteError(DTSError): 157 suite_name: str 158 severity: ClassVar[ErrorSeverity] = ErrorSeverity.BLOCKING_TESTSUITE_ERR 159 160 def __init__(self, suite_name: str) -> None: 161 self.suite_name = suite_name 162 163 def __str__(self) -> str: 164 return f"Blocking suite {self.suite_name} failed." 165