From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 0F04DA00C5; Fri, 4 Nov 2022 12:05:58 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 843C642D36; Fri, 4 Nov 2022 12:05:38 +0100 (CET) Received: from lb.pantheon.sk (lb.pantheon.sk [46.229.239.20]) by mails.dpdk.org (Postfix) with ESMTP id EF16C42D23 for ; Fri, 4 Nov 2022 12:05:35 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by lb.pantheon.sk (Postfix) with ESMTP id 467C61BA5A9; Fri, 4 Nov 2022 12:05:35 +0100 (CET) X-Virus-Scanned: amavisd-new at siecit.sk Received: from lb.pantheon.sk ([127.0.0.1]) by localhost (lb.pantheon.sk [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id lx5LziPEeRq5; Fri, 4 Nov 2022 12:05:34 +0100 (CET) Received: from entguard.lab.pantheon.local (unknown [46.229.239.141]) by lb.pantheon.sk (Postfix) with ESMTP id 73AF41BA5AD; Fri, 4 Nov 2022 12:05:28 +0100 (CET) From: =?UTF-8?q?Juraj=20Linke=C5=A1?= To: thomas@monjalon.net, Honnappa.Nagarahalli@arm.com, ohilyard@iol.unh.edu, lijuan.tu@intel.com, kda@semihalf.com, bruce.richardson@intel.com Cc: dev@dpdk.org, =?UTF-8?q?Juraj=20Linke=C5=A1?= Subject: [PATCH v8 5/9] dts: add remote session abstraction Date: Fri, 4 Nov 2022 11:05:19 +0000 Message-Id: <20221104110523.511367-6-juraj.linkes@pantheon.tech> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221104110523.511367-1-juraj.linkes@pantheon.tech> References: <20221103151934.450887-1-juraj.linkes@pantheon.tech> <20221104110523.511367-1-juraj.linkes@pantheon.tech> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org The abstraction allows for easy switching of implementations of remote connections (ssh, telnet, etc.). It implements some common features, such as logging of commands and their outputs and history bookkeeping and defines methods that must be implemented by derived classes. Signed-off-by: Owen Hilyard Signed-off-by: Juraj Linkeš --- dts/framework/remote_session/__init__.py | 2 + .../remote_session/remote_session.py | 95 +++++++++++++++++++ dts/framework/settings.py | 12 +++ 3 files changed, 109 insertions(+) create mode 100644 dts/framework/remote_session/__init__.py create mode 100644 dts/framework/remote_session/remote_session.py diff --git a/dts/framework/remote_session/__init__.py b/dts/framework/remote_session/__init__.py new file mode 100644 index 0000000000..9bb042a482 --- /dev/null +++ b/dts/framework/remote_session/__init__.py @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2022 PANTHEON.tech s.r.o. diff --git a/dts/framework/remote_session/remote_session.py b/dts/framework/remote_session/remote_session.py new file mode 100644 index 0000000000..33047d9d0a --- /dev/null +++ b/dts/framework/remote_session/remote_session.py @@ -0,0 +1,95 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2010-2014 Intel Corporation +# Copyright(c) 2022 PANTHEON.tech s.r.o. +# Copyright(c) 2022 University of New Hampshire + +import dataclasses +from abc import ABC, abstractmethod + +from framework.config import NodeConfiguration +from framework.logger import DTSLOG +from framework.settings import SETTINGS + + +@dataclasses.dataclass(slots=True, frozen=True) +class HistoryRecord: + name: str + command: str + output: str | int + + +class RemoteSession(ABC): + name: str + hostname: str + ip: str + port: int | None + username: str + password: str + logger: DTSLOG + history: list[HistoryRecord] + _node_config: NodeConfiguration + + def __init__( + self, + node_config: NodeConfiguration, + session_name: str, + logger: DTSLOG, + ): + self._node_config = node_config + + self.name = session_name + self.hostname = node_config.hostname + self.ip = self.hostname + self.port = None + if ":" in self.hostname: + self.ip, port = self.hostname.split(":") + self.port = int(port) + self.username = node_config.user + self.password = node_config.password or "" + self.logger = logger + self.history = [] + + self.logger.info(f"Connecting to {self.username}@{self.hostname}.") + self._connect() + self.logger.info(f"Connection to {self.username}@{self.hostname} successful.") + + @abstractmethod + def _connect(self) -> None: + """ + Create connection to assigned node. + """ + pass + + def send_command(self, command: str, timeout: float = SETTINGS.timeout) -> str: + self.logger.info(f"Sending: {command}") + out = self._send_command(command, timeout) + self.logger.debug(f"Received from {command}: {out}") + self._history_add(command=command, output=out) + return out + + @abstractmethod + def _send_command(self, command: str, timeout: float) -> str: + """ + Send a command and return the output. + """ + + def _history_add(self, command: str, output: str) -> None: + self.history.append( + HistoryRecord(name=self.name, command=command, output=output) + ) + + def close(self, force: bool = False) -> None: + self.logger.logger_exit() + self._close(force) + + @abstractmethod + def _close(self, force: bool = False) -> None: + """ + Close the remote session, freeing all used resources. + """ + + @abstractmethod + def is_alive(self) -> bool: + """ + Check whether the session is still responding. + """ diff --git a/dts/framework/settings.py b/dts/framework/settings.py index b6c5bba2b9..800f2c7b7f 100644 --- a/dts/framework/settings.py +++ b/dts/framework/settings.py @@ -58,6 +58,7 @@ def __call__( class _Settings: config_file_path: str output_dir: str + timeout: float verbose: bool @@ -82,6 +83,16 @@ def _get_parser() -> argparse.ArgumentParser: help="[DTS_OUTPUT_DIR] Output directory where dts logs and results are saved.", ) + parser.add_argument( + "-t", + "--timeout", + action=_env_arg("DTS_TIMEOUT"), + default=15, + required=False, + help="[DTS_TIMEOUT] The default timeout for all DTS operations except for " + "compiling DPDK.", + ) + parser.add_argument( "-v", "--verbose", @@ -100,6 +111,7 @@ def _get_settings() -> _Settings: return _Settings( config_file_path=parsed_args.config_file, output_dir=parsed_args.output_dir, + timeout=float(parsed_args.timeout), verbose=(parsed_args.verbose == "Y"), ) -- 2.30.2