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