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 53b8dd3b9SLuca 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š #: 35818fe14eSLuca Vizzarro INTERNAL_ERR = 5 36818fe14eSLuca Vizzarro #: 37680d8a24SJuraj Linkeš DPDK_BUILD_ERR = 10 386ef07151SJuraj Linkeš #: 396fc05ca7SJuraj Linkeš TESTCASE_VERIFY_ERR = 20 406ef07151SJuraj Linkeš #: 4188489c05SJeremy Spewock BLOCKING_TESTSUITE_ERR = 25 4278534506SJuraj Linkeš 4378534506SJuraj Linkeš 4478534506SJuraj Linkešclass DTSError(Exception): 456ef07151SJuraj Linkeš """The base exception from which all DTS exceptions are subclassed. 466ef07151SJuraj Linkeš 476ef07151SJuraj Linkeš Do not use this exception, only use subclassed exceptions. 4878534506SJuraj Linkeš """ 4978534506SJuraj Linkeš 506ef07151SJuraj Linkeš #: 5178534506SJuraj Linkeš severity: ClassVar[ErrorSeverity] = ErrorSeverity.GENERIC_ERR 5278534506SJuraj Linkeš 5378534506SJuraj Linkeš 5478534506SJuraj Linkešclass SSHConnectionError(DTSError): 556ef07151SJuraj Linkeš """An unsuccessful SSH connection.""" 56812c4071SJuraj Linkeš 576ef07151SJuraj Linkeš #: 5878534506SJuraj Linkeš severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR 59840b1e01SJuraj Linkeš _host: str 60840b1e01SJuraj Linkeš _errors: list[str] 61812c4071SJuraj Linkeš 62b8bdc4c5SJuraj Linkeš def __init__(self, host: str, errors: list[str] | None = None): 636ef07151SJuraj Linkeš """Define the meaning of the first two arguments. 646ef07151SJuraj Linkeš 656ef07151SJuraj Linkeš Args: 666ef07151SJuraj Linkeš host: The hostname to which we're trying to connect. 676ef07151SJuraj Linkeš errors: Any errors that occurred during the connection attempt. 686ef07151SJuraj Linkeš """ 69840b1e01SJuraj Linkeš self._host = host 70840b1e01SJuraj Linkeš self._errors = [] if errors is None else errors 71812c4071SJuraj Linkeš 72812c4071SJuraj Linkeš def __str__(self) -> str: 736ef07151SJuraj Linkeš """Include the errors in the string representation.""" 74840b1e01SJuraj Linkeš message = f"Error trying to connect with {self._host}." 75840b1e01SJuraj Linkeš if self._errors: 76840b1e01SJuraj Linkeš message += f" Errors encountered while retrying: {', '.join(self._errors)}" 77b8bdc4c5SJuraj Linkeš 78b8bdc4c5SJuraj Linkeš return message 79812c4071SJuraj Linkeš 80812c4071SJuraj Linkeš 816713e286SJeremy Spewockclass _SSHTimeoutError(DTSError): 826713e286SJeremy Spewock """The execution of a command via SSH timed out. 836713e286SJeremy Spewock 846713e286SJeremy Spewock This class is private and meant to be raised as its interactive and non-interactive variants. 856713e286SJeremy Spewock """ 866713e286SJeremy Spewock 876713e286SJeremy Spewock #: 886713e286SJeremy Spewock severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR 896713e286SJeremy Spewock _command: str 906713e286SJeremy Spewock 916713e286SJeremy Spewock def __init__(self, command: str): 926713e286SJeremy Spewock """Define the meaning of the first argument. 936713e286SJeremy Spewock 946713e286SJeremy Spewock Args: 956713e286SJeremy Spewock command: The executed command. 966713e286SJeremy Spewock """ 976713e286SJeremy Spewock self._command = command 986713e286SJeremy Spewock 996713e286SJeremy Spewock def __str__(self) -> str: 1006713e286SJeremy Spewock """Add some context to the string representation.""" 1016713e286SJeremy Spewock return f"{self._command} execution timed out." 1026713e286SJeremy Spewock 1036713e286SJeremy Spewock 1046713e286SJeremy Spewockclass SSHTimeoutError(_SSHTimeoutError): 1056713e286SJeremy Spewock """The execution of a command on a non-interactive SSH session timed out.""" 1066713e286SJeremy Spewock 1076713e286SJeremy Spewock 1086713e286SJeremy Spewockclass InteractiveSSHTimeoutError(_SSHTimeoutError): 1096713e286SJeremy Spewock """The execution of a command on an interactive SSH session timed out.""" 1106713e286SJeremy Spewock 1116713e286SJeremy Spewock 1126713e286SJeremy Spewockclass _SSHSessionDeadError(DTSError): 1136713e286SJeremy Spewock """The SSH session is no longer alive. 1146713e286SJeremy Spewock 1156713e286SJeremy Spewock This class is private and meant to be raised as its interactive and non-interactive variants. 1166713e286SJeremy Spewock """ 117812c4071SJuraj Linkeš 1186ef07151SJuraj Linkeš #: 11978534506SJuraj Linkeš severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR 120840b1e01SJuraj Linkeš _host: str 121812c4071SJuraj Linkeš 122812c4071SJuraj Linkeš def __init__(self, host: str): 1236ef07151SJuraj Linkeš """Define the meaning of the first argument. 1246ef07151SJuraj Linkeš 1256ef07151SJuraj Linkeš Args: 1266ef07151SJuraj Linkeš host: The hostname of the disconnected node. 1276ef07151SJuraj Linkeš """ 128840b1e01SJuraj Linkeš self._host = host 129812c4071SJuraj Linkeš 130812c4071SJuraj Linkeš def __str__(self) -> str: 1316ef07151SJuraj Linkeš """Add some context to the string representation.""" 1326ef07151SJuraj Linkeš return f"SSH session with {self._host} has died." 13378534506SJuraj Linkeš 13478534506SJuraj Linkeš 1356713e286SJeremy Spewockclass SSHSessionDeadError(_SSHSessionDeadError): 1366713e286SJeremy Spewock """Non-interactive SSH session has died.""" 1376713e286SJeremy Spewock 1386713e286SJeremy Spewock 1396713e286SJeremy Spewockclass InteractiveSSHSessionDeadError(_SSHSessionDeadError): 1406713e286SJeremy Spewock """Interactive SSH session as died.""" 1416713e286SJeremy Spewock 1426713e286SJeremy Spewock 14378534506SJuraj Linkešclass ConfigurationError(DTSError): 1446ef07151SJuraj Linkeš """An invalid configuration.""" 14578534506SJuraj Linkeš 1466ef07151SJuraj Linkeš #: 14778534506SJuraj Linkeš severity: ClassVar[ErrorSeverity] = ErrorSeverity.CONFIG_ERR 148ad80f550SJuraj Linkeš 149ad80f550SJuraj Linkeš 150ad80f550SJuraj Linkešclass RemoteCommandExecutionError(DTSError): 1516ef07151SJuraj Linkeš """An unsuccessful execution of a remote command.""" 152ad80f550SJuraj Linkeš 1536ef07151SJuraj Linkeš #: 154ad80f550SJuraj Linkeš severity: ClassVar[ErrorSeverity] = ErrorSeverity.REMOTE_CMD_EXEC_ERR 1556ef07151SJuraj Linkeš #: The executed command. 156840b1e01SJuraj Linkeš command: str 1573b8dd3b9SLuca Vizzarro _command_stderr: str 158840b1e01SJuraj Linkeš _command_return_code: int 159ad80f550SJuraj Linkeš 1603b8dd3b9SLuca Vizzarro def __init__(self, command: str, command_stderr: str, command_return_code: int): 1616ef07151SJuraj Linkeš """Define the meaning of the first two arguments. 1626ef07151SJuraj Linkeš 1636ef07151SJuraj Linkeš Args: 1646ef07151SJuraj Linkeš command: The executed command. 1653b8dd3b9SLuca Vizzarro command_stderr: The stderr of the executed command. 1666ef07151SJuraj Linkeš command_return_code: The return code of the executed command. 1676ef07151SJuraj Linkeš """ 168ad80f550SJuraj Linkeš self.command = command 1693b8dd3b9SLuca Vizzarro self._command_stderr = command_stderr 170840b1e01SJuraj Linkeš self._command_return_code = command_return_code 171ad80f550SJuraj Linkeš 172ad80f550SJuraj Linkeš def __str__(self) -> str: 1733b8dd3b9SLuca Vizzarro """Include the command, its return code and stderr in the string representation.""" 1743b8dd3b9SLuca Vizzarro return ( 1753b8dd3b9SLuca Vizzarro f"Command '{self.command}' returned a non-zero exit code: " 1763b8dd3b9SLuca Vizzarro f"{self._command_return_code}\nStderr: {self._command_stderr}" 1773b8dd3b9SLuca Vizzarro ) 178680d8a24SJuraj Linkeš 179680d8a24SJuraj Linkeš 180369d34b8SJeremy Spewockclass InteractiveCommandExecutionError(DTSError): 181369d34b8SJeremy Spewock """An unsuccessful execution of a remote command in an interactive environment.""" 182369d34b8SJeremy Spewock 183369d34b8SJeremy Spewock #: 184369d34b8SJeremy Spewock severity: ClassVar[ErrorSeverity] = ErrorSeverity.REMOTE_CMD_EXEC_ERR 185369d34b8SJeremy Spewock 186369d34b8SJeremy Spewock 187*f9957667STomáš Ďurovecclass RemoteFileNotFoundError(DTSError): 188*f9957667STomáš Ďurovec """A remote file or directory is requested but doesn’t exist.""" 189680d8a24SJuraj Linkeš 1906ef07151SJuraj Linkeš #: 191680d8a24SJuraj Linkeš severity: ClassVar[ErrorSeverity] = ErrorSeverity.REMOTE_CMD_EXEC_ERR 192680d8a24SJuraj Linkeš 193680d8a24SJuraj Linkeš 194680d8a24SJuraj Linkešclass DPDKBuildError(DTSError): 1956ef07151SJuraj Linkeš """A DPDK build failure.""" 196680d8a24SJuraj Linkeš 1976ef07151SJuraj Linkeš #: 198680d8a24SJuraj Linkeš severity: ClassVar[ErrorSeverity] = ErrorSeverity.DPDK_BUILD_ERR 1996fc05ca7SJuraj Linkeš 2006fc05ca7SJuraj Linkeš 2016fc05ca7SJuraj Linkešclass TestCaseVerifyError(DTSError): 2026ef07151SJuraj Linkeš """A test case failure.""" 2036fc05ca7SJuraj Linkeš 2046ef07151SJuraj Linkeš #: 2056fc05ca7SJuraj Linkeš severity: ClassVar[ErrorSeverity] = ErrorSeverity.TESTCASE_VERIFY_ERR 2066fc05ca7SJuraj Linkeš 20788489c05SJeremy Spewock 20888489c05SJeremy Spewockclass BlockingTestSuiteError(DTSError): 2096ef07151SJuraj Linkeš """A failure in a blocking test suite.""" 2106ef07151SJuraj Linkeš 2116ef07151SJuraj Linkeš #: 21288489c05SJeremy Spewock severity: ClassVar[ErrorSeverity] = ErrorSeverity.BLOCKING_TESTSUITE_ERR 213840b1e01SJuraj Linkeš _suite_name: str 21488489c05SJeremy Spewock 21588489c05SJeremy Spewock def __init__(self, suite_name: str) -> None: 2166ef07151SJuraj Linkeš """Define the meaning of the first argument. 2176ef07151SJuraj Linkeš 2186ef07151SJuraj Linkeš Args: 2196ef07151SJuraj Linkeš suite_name: The blocking test suite. 2206ef07151SJuraj Linkeš """ 221840b1e01SJuraj Linkeš self._suite_name = suite_name 22288489c05SJeremy Spewock 22388489c05SJeremy Spewock def __str__(self) -> str: 2246ef07151SJuraj Linkeš """Add some context to the string representation.""" 225840b1e01SJuraj Linkeš return f"Blocking suite {self._suite_name} failed." 226818fe14eSLuca Vizzarro 227818fe14eSLuca Vizzarro 228818fe14eSLuca Vizzarroclass InternalError(DTSError): 229818fe14eSLuca Vizzarro """An internal error or bug has occurred in DTS.""" 230818fe14eSLuca Vizzarro 231818fe14eSLuca Vizzarro #: 232818fe14eSLuca Vizzarro severity: ClassVar[ErrorSeverity] = ErrorSeverity.INTERNAL_ERR 233