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 29 30class DTSError(Exception): 31 """ 32 The base exception from which all DTS exceptions are derived. 33 Stores error severity. 34 """ 35 36 severity: ClassVar[ErrorSeverity] = ErrorSeverity.GENERIC_ERR 37 38 39class SSHTimeoutError(DTSError): 40 """ 41 Command execution timeout. 42 """ 43 44 command: str 45 output: str 46 severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR 47 48 def __init__(self, command: str, output: str): 49 self.command = command 50 self.output = output 51 52 def __str__(self) -> str: 53 return f"TIMEOUT on {self.command}" 54 55 def get_output(self) -> str: 56 return self.output 57 58 59class SSHConnectionError(DTSError): 60 """ 61 SSH connection error. 62 """ 63 64 host: str 65 errors: list[str] 66 severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR 67 68 def __init__(self, host: str, errors: list[str] | None = None): 69 self.host = host 70 self.errors = [] if errors is None else errors 71 72 def __str__(self) -> str: 73 message = f"Error trying to connect with {self.host}." 74 if self.errors: 75 message += f" Errors encountered while retrying: {', '.join(self.errors)}" 76 77 return message 78 79 80class SSHSessionDeadError(DTSError): 81 """ 82 SSH session is not alive. 83 It can no longer be used. 84 """ 85 86 host: str 87 severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR 88 89 def __init__(self, host: str): 90 self.host = host 91 92 def __str__(self) -> str: 93 return f"SSH session with {self.host} has died" 94 95 96class ConfigurationError(DTSError): 97 """ 98 Raised when an invalid configuration is encountered. 99 """ 100 101 severity: ClassVar[ErrorSeverity] = ErrorSeverity.CONFIG_ERR 102 103 104class RemoteCommandExecutionError(DTSError): 105 """ 106 Raised when a command executed on a Node returns a non-zero exit status. 107 """ 108 109 command: str 110 command_return_code: int 111 severity: ClassVar[ErrorSeverity] = ErrorSeverity.REMOTE_CMD_EXEC_ERR 112 113 def __init__(self, command: str, command_return_code: int): 114 self.command = command 115 self.command_return_code = command_return_code 116 117 def __str__(self) -> str: 118 return ( 119 f"Command {self.command} returned a non-zero exit code: " 120 f"{self.command_return_code}" 121 ) 122 123 124class RemoteDirectoryExistsError(DTSError): 125 """ 126 Raised when a remote directory to be created already exists. 127 """ 128 129 severity: ClassVar[ErrorSeverity] = ErrorSeverity.REMOTE_CMD_EXEC_ERR 130 131 132class DPDKBuildError(DTSError): 133 """ 134 Raised when DPDK build fails for any reason. 135 """ 136 137 severity: ClassVar[ErrorSeverity] = ErrorSeverity.DPDK_BUILD_ERR 138 139 140class TestCaseVerifyError(DTSError): 141 """ 142 Used in test cases to verify the expected behavior. 143 """ 144 145 value: str 146 severity: ClassVar[ErrorSeverity] = ErrorSeverity.TESTCASE_VERIFY_ERR 147 148 def __init__(self, value: str): 149 self.value = value 150 151 def __str__(self) -> str: 152 return repr(self.value) 153