xref: /dpdk/dts/framework/exception.py (revision 3b8dd3b9c0c86d6077c5633e8e7edea6a2269cc6)
1812c4071SJuraj Linkeš# SPDX-License-Identifier: BSD-3-Clause
2812c4071SJuraj Linkeš# Copyright(c) 2010-2014 Intel Corporation
378534506SJuraj Linkeš# Copyright(c) 2022-2023 PANTHEON.tech s.r.o.
478534506SJuraj Linkeš# Copyright(c) 2022-2023 University of New Hampshire
5*3b8dd3b9SLuca Vizzarro# Copyright(c) 2024 Arm Limited
6812c4071SJuraj Linkeš
76ef07151SJuraj Linkeš"""DTS exceptions.
86ef07151SJuraj Linkeš
96ef07151SJuraj LinkešThe exceptions all have different severities expressed as an integer.
106ef07151SJuraj LinkešThe highest severity of all raised exceptions is used as the exit code of DTS.
11812c4071SJuraj Linkeš"""
12812c4071SJuraj Linkeš
1378534506SJuraj Linkešfrom enum import IntEnum, unique
1478534506SJuraj Linkešfrom typing import ClassVar
15812c4071SJuraj Linkeš
1678534506SJuraj Linkeš
1778534506SJuraj Linkeš@unique
1878534506SJuraj Linkešclass ErrorSeverity(IntEnum):
196ef07151SJuraj Linkeš    """The severity of errors that occur during DTS execution.
206ef07151SJuraj Linkeš
2178534506SJuraj Linkeš    All exceptions are caught and the most severe error is used as return code.
2278534506SJuraj Linkeš    """
2378534506SJuraj Linkeš
246ef07151SJuraj Linkeš    #:
2578534506SJuraj Linkeš    NO_ERR = 0
266ef07151SJuraj Linkeš    #:
2778534506SJuraj Linkeš    GENERIC_ERR = 1
286ef07151SJuraj Linkeš    #:
2978534506SJuraj Linkeš    CONFIG_ERR = 2
306ef07151SJuraj Linkeš    #:
31ad80f550SJuraj Linkeš    REMOTE_CMD_EXEC_ERR = 3
326ef07151SJuraj Linkeš    #:
33ad80f550SJuraj Linkeš    SSH_ERR = 4
346ef07151SJuraj Linkeš    #:
35680d8a24SJuraj Linkeš    DPDK_BUILD_ERR = 10
366ef07151SJuraj Linkeš    #:
376fc05ca7SJuraj Linkeš    TESTCASE_VERIFY_ERR = 20
386ef07151SJuraj Linkeš    #:
3988489c05SJeremy Spewock    BLOCKING_TESTSUITE_ERR = 25
4078534506SJuraj Linkeš
4178534506SJuraj Linkeš
4278534506SJuraj Linkešclass DTSError(Exception):
436ef07151SJuraj Linkeš    """The base exception from which all DTS exceptions are subclassed.
446ef07151SJuraj Linkeš
456ef07151SJuraj Linkeš    Do not use this exception, only use subclassed exceptions.
4678534506SJuraj Linkeš    """
4778534506SJuraj Linkeš
486ef07151SJuraj Linkeš    #:
4978534506SJuraj Linkeš    severity: ClassVar[ErrorSeverity] = ErrorSeverity.GENERIC_ERR
5078534506SJuraj Linkeš
5178534506SJuraj Linkeš
5278534506SJuraj Linkešclass SSHTimeoutError(DTSError):
536ef07151SJuraj Linkeš    """The SSH execution of a command timed out."""
54812c4071SJuraj Linkeš
556ef07151SJuraj Linkeš    #:
5678534506SJuraj Linkeš    severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR
57840b1e01SJuraj Linkeš    _command: str
58812c4071SJuraj Linkeš
59840b1e01SJuraj Linkeš    def __init__(self, command: str):
606ef07151SJuraj Linkeš        """Define the meaning of the first argument.
616ef07151SJuraj Linkeš
626ef07151SJuraj Linkeš        Args:
636ef07151SJuraj Linkeš            command: The executed command.
646ef07151SJuraj Linkeš        """
65840b1e01SJuraj Linkeš        self._command = command
66812c4071SJuraj Linkeš
67812c4071SJuraj Linkeš    def __str__(self) -> str:
686ef07151SJuraj Linkeš        """Add some context to the string representation."""
696ef07151SJuraj Linkeš        return f"{self._command} execution timed out."
70812c4071SJuraj Linkeš
71812c4071SJuraj Linkeš
7278534506SJuraj Linkešclass SSHConnectionError(DTSError):
736ef07151SJuraj Linkeš    """An unsuccessful SSH connection."""
74812c4071SJuraj Linkeš
756ef07151SJuraj Linkeš    #:
7678534506SJuraj Linkeš    severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR
77840b1e01SJuraj Linkeš    _host: str
78840b1e01SJuraj Linkeš    _errors: list[str]
79812c4071SJuraj Linkeš
80b8bdc4c5SJuraj Linkeš    def __init__(self, host: str, errors: list[str] | None = None):
816ef07151SJuraj Linkeš        """Define the meaning of the first two arguments.
826ef07151SJuraj Linkeš
836ef07151SJuraj Linkeš        Args:
846ef07151SJuraj Linkeš            host: The hostname to which we're trying to connect.
856ef07151SJuraj Linkeš            errors: Any errors that occurred during the connection attempt.
866ef07151SJuraj Linkeš        """
87840b1e01SJuraj Linkeš        self._host = host
88840b1e01SJuraj Linkeš        self._errors = [] if errors is None else errors
89812c4071SJuraj Linkeš
90812c4071SJuraj Linkeš    def __str__(self) -> str:
916ef07151SJuraj Linkeš        """Include the errors in the string representation."""
92840b1e01SJuraj Linkeš        message = f"Error trying to connect with {self._host}."
93840b1e01SJuraj Linkeš        if self._errors:
94840b1e01SJuraj Linkeš            message += f" Errors encountered while retrying: {', '.join(self._errors)}"
95b8bdc4c5SJuraj Linkeš
96b8bdc4c5SJuraj Linkeš        return message
97812c4071SJuraj Linkeš
98812c4071SJuraj Linkeš
9978534506SJuraj Linkešclass SSHSessionDeadError(DTSError):
1006ef07151SJuraj Linkeš    """The SSH session is no longer alive."""
101812c4071SJuraj Linkeš
1026ef07151SJuraj Linkeš    #:
10378534506SJuraj Linkeš    severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR
104840b1e01SJuraj Linkeš    _host: str
105812c4071SJuraj Linkeš
106812c4071SJuraj Linkeš    def __init__(self, host: str):
1076ef07151SJuraj Linkeš        """Define the meaning of the first argument.
1086ef07151SJuraj Linkeš
1096ef07151SJuraj Linkeš        Args:
1106ef07151SJuraj Linkeš            host: The hostname of the disconnected node.
1116ef07151SJuraj Linkeš        """
112840b1e01SJuraj Linkeš        self._host = host
113812c4071SJuraj Linkeš
114812c4071SJuraj Linkeš    def __str__(self) -> str:
1156ef07151SJuraj Linkeš        """Add some context to the string representation."""
1166ef07151SJuraj Linkeš        return f"SSH session with {self._host} has died."
11778534506SJuraj Linkeš
11878534506SJuraj Linkeš
11978534506SJuraj Linkešclass ConfigurationError(DTSError):
1206ef07151SJuraj Linkeš    """An invalid configuration."""
12178534506SJuraj Linkeš
1226ef07151SJuraj Linkeš    #:
12378534506SJuraj Linkeš    severity: ClassVar[ErrorSeverity] = ErrorSeverity.CONFIG_ERR
124ad80f550SJuraj Linkeš
125ad80f550SJuraj Linkeš
126ad80f550SJuraj Linkešclass RemoteCommandExecutionError(DTSError):
1276ef07151SJuraj Linkeš    """An unsuccessful execution of a remote command."""
128ad80f550SJuraj Linkeš
1296ef07151SJuraj Linkeš    #:
130ad80f550SJuraj Linkeš    severity: ClassVar[ErrorSeverity] = ErrorSeverity.REMOTE_CMD_EXEC_ERR
1316ef07151SJuraj Linkeš    #: The executed command.
132840b1e01SJuraj Linkeš    command: str
133*3b8dd3b9SLuca Vizzarro    _command_stderr: str
134840b1e01SJuraj Linkeš    _command_return_code: int
135ad80f550SJuraj Linkeš
136*3b8dd3b9SLuca Vizzarro    def __init__(self, command: str, command_stderr: str, command_return_code: int):
1376ef07151SJuraj Linkeš        """Define the meaning of the first two arguments.
1386ef07151SJuraj Linkeš
1396ef07151SJuraj Linkeš        Args:
1406ef07151SJuraj Linkeš            command: The executed command.
141*3b8dd3b9SLuca Vizzarro            command_stderr: The stderr of the executed command.
1426ef07151SJuraj Linkeš            command_return_code: The return code of the executed command.
1436ef07151SJuraj Linkeš        """
144ad80f550SJuraj Linkeš        self.command = command
145*3b8dd3b9SLuca Vizzarro        self._command_stderr = command_stderr
146840b1e01SJuraj Linkeš        self._command_return_code = command_return_code
147ad80f550SJuraj Linkeš
148ad80f550SJuraj Linkeš    def __str__(self) -> str:
149*3b8dd3b9SLuca Vizzarro        """Include the command, its return code and stderr in the string representation."""
150*3b8dd3b9SLuca Vizzarro        return (
151*3b8dd3b9SLuca Vizzarro            f"Command '{self.command}' returned a non-zero exit code: "
152*3b8dd3b9SLuca Vizzarro            f"{self._command_return_code}\nStderr: {self._command_stderr}"
153*3b8dd3b9SLuca Vizzarro        )
154680d8a24SJuraj Linkeš
155680d8a24SJuraj Linkeš
156369d34b8SJeremy Spewockclass InteractiveCommandExecutionError(DTSError):
157369d34b8SJeremy Spewock    """An unsuccessful execution of a remote command in an interactive environment."""
158369d34b8SJeremy Spewock
159369d34b8SJeremy Spewock    #:
160369d34b8SJeremy Spewock    severity: ClassVar[ErrorSeverity] = ErrorSeverity.REMOTE_CMD_EXEC_ERR
161369d34b8SJeremy Spewock
162369d34b8SJeremy Spewock
163680d8a24SJuraj Linkešclass RemoteDirectoryExistsError(DTSError):
1646ef07151SJuraj Linkeš    """A directory that exists on a remote node."""
165680d8a24SJuraj Linkeš
1666ef07151SJuraj Linkeš    #:
167680d8a24SJuraj Linkeš    severity: ClassVar[ErrorSeverity] = ErrorSeverity.REMOTE_CMD_EXEC_ERR
168680d8a24SJuraj Linkeš
169680d8a24SJuraj Linkeš
170680d8a24SJuraj Linkešclass DPDKBuildError(DTSError):
1716ef07151SJuraj Linkeš    """A DPDK build failure."""
172680d8a24SJuraj Linkeš
1736ef07151SJuraj Linkeš    #:
174680d8a24SJuraj Linkeš    severity: ClassVar[ErrorSeverity] = ErrorSeverity.DPDK_BUILD_ERR
1756fc05ca7SJuraj Linkeš
1766fc05ca7SJuraj Linkeš
1776fc05ca7SJuraj Linkešclass TestCaseVerifyError(DTSError):
1786ef07151SJuraj Linkeš    """A test case failure."""
1796fc05ca7SJuraj Linkeš
1806ef07151SJuraj Linkeš    #:
1816fc05ca7SJuraj Linkeš    severity: ClassVar[ErrorSeverity] = ErrorSeverity.TESTCASE_VERIFY_ERR
1826fc05ca7SJuraj Linkeš
18388489c05SJeremy Spewock
18488489c05SJeremy Spewockclass BlockingTestSuiteError(DTSError):
1856ef07151SJuraj Linkeš    """A failure in a blocking test suite."""
1866ef07151SJuraj Linkeš
1876ef07151SJuraj Linkeš    #:
18888489c05SJeremy Spewock    severity: ClassVar[ErrorSeverity] = ErrorSeverity.BLOCKING_TESTSUITE_ERR
189840b1e01SJuraj Linkeš    _suite_name: str
19088489c05SJeremy Spewock
19188489c05SJeremy Spewock    def __init__(self, suite_name: str) -> None:
1926ef07151SJuraj Linkeš        """Define the meaning of the first argument.
1936ef07151SJuraj Linkeš
1946ef07151SJuraj Linkeš        Args:
1956ef07151SJuraj Linkeš            suite_name: The blocking test suite.
1966ef07151SJuraj Linkeš        """
197840b1e01SJuraj Linkeš        self._suite_name = suite_name
19888489c05SJeremy Spewock
19988489c05SJeremy Spewock    def __str__(self) -> str:
2006ef07151SJuraj Linkeš        """Add some context to the string representation."""
201840b1e01SJuraj Linkeš        return f"Blocking suite {self._suite_name} failed."
202