xref: /dpdk/dts/framework/exception.py (revision 369d34b83b4b53975c9e09c54cb5a257273ce610)
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
5812c4071SJuraj Linkeš
66ef07151SJuraj Linkeš"""DTS exceptions.
76ef07151SJuraj Linkeš
86ef07151SJuraj LinkešThe exceptions all have different severities expressed as an integer.
96ef07151SJuraj LinkešThe highest severity of all raised exceptions is used as the exit code of DTS.
10812c4071SJuraj Linkeš"""
11812c4071SJuraj Linkeš
1278534506SJuraj Linkešfrom enum import IntEnum, unique
1378534506SJuraj Linkešfrom typing import ClassVar
14812c4071SJuraj Linkeš
1578534506SJuraj Linkeš
1678534506SJuraj Linkeš@unique
1778534506SJuraj Linkešclass ErrorSeverity(IntEnum):
186ef07151SJuraj Linkeš    """The severity of errors that occur during DTS execution.
196ef07151SJuraj Linkeš
2078534506SJuraj Linkeš    All exceptions are caught and the most severe error is used as return code.
2178534506SJuraj Linkeš    """
2278534506SJuraj Linkeš
236ef07151SJuraj Linkeš    #:
2478534506SJuraj Linkeš    NO_ERR = 0
256ef07151SJuraj Linkeš    #:
2678534506SJuraj Linkeš    GENERIC_ERR = 1
276ef07151SJuraj Linkeš    #:
2878534506SJuraj Linkeš    CONFIG_ERR = 2
296ef07151SJuraj Linkeš    #:
30ad80f550SJuraj Linkeš    REMOTE_CMD_EXEC_ERR = 3
316ef07151SJuraj Linkeš    #:
32ad80f550SJuraj Linkeš    SSH_ERR = 4
336ef07151SJuraj Linkeš    #:
34680d8a24SJuraj Linkeš    DPDK_BUILD_ERR = 10
356ef07151SJuraj Linkeš    #:
366fc05ca7SJuraj Linkeš    TESTCASE_VERIFY_ERR = 20
376ef07151SJuraj Linkeš    #:
3888489c05SJeremy Spewock    BLOCKING_TESTSUITE_ERR = 25
3978534506SJuraj Linkeš
4078534506SJuraj Linkeš
4178534506SJuraj Linkešclass DTSError(Exception):
426ef07151SJuraj Linkeš    """The base exception from which all DTS exceptions are subclassed.
436ef07151SJuraj Linkeš
446ef07151SJuraj Linkeš    Do not use this exception, only use subclassed exceptions.
4578534506SJuraj Linkeš    """
4678534506SJuraj Linkeš
476ef07151SJuraj Linkeš    #:
4878534506SJuraj Linkeš    severity: ClassVar[ErrorSeverity] = ErrorSeverity.GENERIC_ERR
4978534506SJuraj Linkeš
5078534506SJuraj Linkeš
5178534506SJuraj Linkešclass SSHTimeoutError(DTSError):
526ef07151SJuraj Linkeš    """The SSH execution of a command timed out."""
53812c4071SJuraj Linkeš
546ef07151SJuraj Linkeš    #:
5578534506SJuraj Linkeš    severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR
56840b1e01SJuraj Linkeš    _command: str
57812c4071SJuraj Linkeš
58840b1e01SJuraj Linkeš    def __init__(self, command: str):
596ef07151SJuraj Linkeš        """Define the meaning of the first argument.
606ef07151SJuraj Linkeš
616ef07151SJuraj Linkeš        Args:
626ef07151SJuraj Linkeš            command: The executed command.
636ef07151SJuraj Linkeš        """
64840b1e01SJuraj Linkeš        self._command = command
65812c4071SJuraj Linkeš
66812c4071SJuraj Linkeš    def __str__(self) -> str:
676ef07151SJuraj Linkeš        """Add some context to the string representation."""
686ef07151SJuraj Linkeš        return f"{self._command} execution timed out."
69812c4071SJuraj Linkeš
70812c4071SJuraj Linkeš
7178534506SJuraj Linkešclass SSHConnectionError(DTSError):
726ef07151SJuraj Linkeš    """An unsuccessful SSH connection."""
73812c4071SJuraj Linkeš
746ef07151SJuraj Linkeš    #:
7578534506SJuraj Linkeš    severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR
76840b1e01SJuraj Linkeš    _host: str
77840b1e01SJuraj Linkeš    _errors: list[str]
78812c4071SJuraj Linkeš
79b8bdc4c5SJuraj Linkeš    def __init__(self, host: str, errors: list[str] | None = None):
806ef07151SJuraj Linkeš        """Define the meaning of the first two arguments.
816ef07151SJuraj Linkeš
826ef07151SJuraj Linkeš        Args:
836ef07151SJuraj Linkeš            host: The hostname to which we're trying to connect.
846ef07151SJuraj Linkeš            errors: Any errors that occurred during the connection attempt.
856ef07151SJuraj Linkeš        """
86840b1e01SJuraj Linkeš        self._host = host
87840b1e01SJuraj Linkeš        self._errors = [] if errors is None else errors
88812c4071SJuraj Linkeš
89812c4071SJuraj Linkeš    def __str__(self) -> str:
906ef07151SJuraj Linkeš        """Include the errors in the string representation."""
91840b1e01SJuraj Linkeš        message = f"Error trying to connect with {self._host}."
92840b1e01SJuraj Linkeš        if self._errors:
93840b1e01SJuraj Linkeš            message += f" Errors encountered while retrying: {', '.join(self._errors)}"
94b8bdc4c5SJuraj Linkeš
95b8bdc4c5SJuraj Linkeš        return message
96812c4071SJuraj Linkeš
97812c4071SJuraj Linkeš
9878534506SJuraj Linkešclass SSHSessionDeadError(DTSError):
996ef07151SJuraj Linkeš    """The SSH session is no longer alive."""
100812c4071SJuraj Linkeš
1016ef07151SJuraj Linkeš    #:
10278534506SJuraj Linkeš    severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR
103840b1e01SJuraj Linkeš    _host: str
104812c4071SJuraj Linkeš
105812c4071SJuraj Linkeš    def __init__(self, host: str):
1066ef07151SJuraj Linkeš        """Define the meaning of the first argument.
1076ef07151SJuraj Linkeš
1086ef07151SJuraj Linkeš        Args:
1096ef07151SJuraj Linkeš            host: The hostname of the disconnected node.
1106ef07151SJuraj Linkeš        """
111840b1e01SJuraj Linkeš        self._host = host
112812c4071SJuraj Linkeš
113812c4071SJuraj Linkeš    def __str__(self) -> str:
1146ef07151SJuraj Linkeš        """Add some context to the string representation."""
1156ef07151SJuraj Linkeš        return f"SSH session with {self._host} has died."
11678534506SJuraj Linkeš
11778534506SJuraj Linkeš
11878534506SJuraj Linkešclass ConfigurationError(DTSError):
1196ef07151SJuraj Linkeš    """An invalid configuration."""
12078534506SJuraj Linkeš
1216ef07151SJuraj Linkeš    #:
12278534506SJuraj Linkeš    severity: ClassVar[ErrorSeverity] = ErrorSeverity.CONFIG_ERR
123ad80f550SJuraj Linkeš
124ad80f550SJuraj Linkeš
125ad80f550SJuraj Linkešclass RemoteCommandExecutionError(DTSError):
1266ef07151SJuraj Linkeš    """An unsuccessful execution of a remote command."""
127ad80f550SJuraj Linkeš
1286ef07151SJuraj Linkeš    #:
129ad80f550SJuraj Linkeš    severity: ClassVar[ErrorSeverity] = ErrorSeverity.REMOTE_CMD_EXEC_ERR
1306ef07151SJuraj Linkeš    #: The executed command.
131840b1e01SJuraj Linkeš    command: str
132840b1e01SJuraj Linkeš    _command_return_code: int
133ad80f550SJuraj Linkeš
134ad80f550SJuraj Linkeš    def __init__(self, command: str, command_return_code: int):
1356ef07151SJuraj Linkeš        """Define the meaning of the first two arguments.
1366ef07151SJuraj Linkeš
1376ef07151SJuraj Linkeš        Args:
1386ef07151SJuraj Linkeš            command: The executed command.
1396ef07151SJuraj Linkeš            command_return_code: The return code of the executed command.
1406ef07151SJuraj Linkeš        """
141ad80f550SJuraj Linkeš        self.command = command
142840b1e01SJuraj Linkeš        self._command_return_code = command_return_code
143ad80f550SJuraj Linkeš
144ad80f550SJuraj Linkeš    def __str__(self) -> str:
1456ef07151SJuraj Linkeš        """Include both the command and return code in the string representation."""
146840b1e01SJuraj Linkeš        return f"Command {self.command} returned a non-zero exit code: {self._command_return_code}"
147680d8a24SJuraj Linkeš
148680d8a24SJuraj Linkeš
149*369d34b8SJeremy Spewockclass InteractiveCommandExecutionError(DTSError):
150*369d34b8SJeremy Spewock    """An unsuccessful execution of a remote command in an interactive environment."""
151*369d34b8SJeremy Spewock
152*369d34b8SJeremy Spewock    #:
153*369d34b8SJeremy Spewock    severity: ClassVar[ErrorSeverity] = ErrorSeverity.REMOTE_CMD_EXEC_ERR
154*369d34b8SJeremy Spewock
155*369d34b8SJeremy Spewock
156680d8a24SJuraj Linkešclass RemoteDirectoryExistsError(DTSError):
1576ef07151SJuraj Linkeš    """A directory that exists on a remote node."""
158680d8a24SJuraj Linkeš
1596ef07151SJuraj Linkeš    #:
160680d8a24SJuraj Linkeš    severity: ClassVar[ErrorSeverity] = ErrorSeverity.REMOTE_CMD_EXEC_ERR
161680d8a24SJuraj Linkeš
162680d8a24SJuraj Linkeš
163680d8a24SJuraj Linkešclass DPDKBuildError(DTSError):
1646ef07151SJuraj Linkeš    """A DPDK build failure."""
165680d8a24SJuraj Linkeš
1666ef07151SJuraj Linkeš    #:
167680d8a24SJuraj Linkeš    severity: ClassVar[ErrorSeverity] = ErrorSeverity.DPDK_BUILD_ERR
1686fc05ca7SJuraj Linkeš
1696fc05ca7SJuraj Linkeš
1706fc05ca7SJuraj Linkešclass TestCaseVerifyError(DTSError):
1716ef07151SJuraj Linkeš    """A test case failure."""
1726fc05ca7SJuraj Linkeš
1736ef07151SJuraj Linkeš    #:
1746fc05ca7SJuraj Linkeš    severity: ClassVar[ErrorSeverity] = ErrorSeverity.TESTCASE_VERIFY_ERR
1756fc05ca7SJuraj Linkeš
17688489c05SJeremy Spewock
17788489c05SJeremy Spewockclass BlockingTestSuiteError(DTSError):
1786ef07151SJuraj Linkeš    """A failure in a blocking test suite."""
1796ef07151SJuraj Linkeš
1806ef07151SJuraj Linkeš    #:
18188489c05SJeremy Spewock    severity: ClassVar[ErrorSeverity] = ErrorSeverity.BLOCKING_TESTSUITE_ERR
182840b1e01SJuraj Linkeš    _suite_name: str
18388489c05SJeremy Spewock
18488489c05SJeremy Spewock    def __init__(self, suite_name: str) -> None:
1856ef07151SJuraj Linkeš        """Define the meaning of the first argument.
1866ef07151SJuraj Linkeš
1876ef07151SJuraj Linkeš        Args:
1886ef07151SJuraj Linkeš            suite_name: The blocking test suite.
1896ef07151SJuraj Linkeš        """
190840b1e01SJuraj Linkeš        self._suite_name = suite_name
19188489c05SJeremy Spewock
19288489c05SJeremy Spewock    def __str__(self) -> str:
1936ef07151SJuraj Linkeš        """Add some context to the string representation."""
194840b1e01SJuraj Linkeš        return f"Blocking suite {self._suite_name} failed."
195