xref: /dpdk/dts/framework/exception.py (revision 6903de616a1296e368002687cb43ef3b9fc4699f)
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