get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/119446/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 119446,
    "url": "http://patches.dpdk.org/api/patches/119446/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20221103151934.450887-6-juraj.linkes@pantheon.tech/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20221103151934.450887-6-juraj.linkes@pantheon.tech>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20221103151934.450887-6-juraj.linkes@pantheon.tech",
    "date": "2022-11-03T15:19:30",
    "name": "[v7,5/9] dts: add remote session abstraction",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "41cfd329f3bf98ebb30619a9ce5776c8a8d4ddd4",
    "submitter": {
        "id": 1626,
        "url": "http://patches.dpdk.org/api/people/1626/?format=api",
        "name": "Juraj Linkeš",
        "email": "juraj.linkes@pantheon.tech"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20221103151934.450887-6-juraj.linkes@pantheon.tech/mbox/",
    "series": [
        {
            "id": 25553,
            "url": "http://patches.dpdk.org/api/series/25553/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=25553",
            "date": "2022-11-03T15:19:25",
            "name": "dts: ssh connection to a node",
            "version": 7,
            "mbox": "http://patches.dpdk.org/series/25553/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/119446/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/119446/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 4B6DBA00C2;\n\tThu,  3 Nov 2022 16:20:13 +0100 (CET)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id BE6E842D14;\n\tThu,  3 Nov 2022 16:19:45 +0100 (CET)",
            "from lb.pantheon.sk (lb.pantheon.sk [46.229.239.20])\n by mails.dpdk.org (Postfix) with ESMTP id 9580A42D23\n for <dev@dpdk.org>; Thu,  3 Nov 2022 16:19:43 +0100 (CET)",
            "from localhost (localhost [127.0.0.1])\n by lb.pantheon.sk (Postfix) with ESMTP id 51C161B68FA;\n Thu,  3 Nov 2022 16:19:43 +0100 (CET)",
            "from lb.pantheon.sk ([127.0.0.1])\n by localhost (lb.pantheon.sk [127.0.0.1]) (amavisd-new, port 10024)\n with ESMTP id kWHqW-XNDklo; Thu,  3 Nov 2022 16:19:41 +0100 (CET)",
            "from entguard.lab.pantheon.local (unknown [46.229.239.141])\n by lb.pantheon.sk (Postfix) with ESMTP id 5CAC61BA589;\n Thu,  3 Nov 2022 16:19:37 +0100 (CET)"
        ],
        "X-Virus-Scanned": "amavisd-new at siecit.sk",
        "From": "=?utf-8?q?Juraj_Linke=C5=A1?= <juraj.linkes@pantheon.tech>",
        "To": "",
        "Cc": "dev@dpdk.org, =?utf-8?q?Juraj_Linke=C5=A1?= <juraj.linkes@pantheon.tech>",
        "Subject": "[PATCH v7 5/9] dts: add remote session abstraction",
        "Date": "Thu,  3 Nov 2022 15:19:30 +0000",
        "Message-Id": "<20221103151934.450887-6-juraj.linkes@pantheon.tech>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20221103151934.450887-1-juraj.linkes@pantheon.tech>",
        "References": "<20221013103517.3443997-1-juraj.linkes@pantheon.tech>\n <20221103151934.450887-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 <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "The abstraction allows for easy switching of implementations of remote\nconnections (ssh, telnet, etc.). It implements some common features,\nsuch as logging of commands and their outputs and history bookkeeping\nand defines methods that must be implemented by derived classes.\n\nSigned-off-by: Owen Hilyard <ohilyard@iol.unh.edu>\nSigned-off-by: Juraj Linkeš <juraj.linkes@pantheon.tech>\n---\n dts/framework/remote_session/__init__.py      |  2 +\n .../remote_session/remote_session.py          | 95 +++++++++++++++++++\n dts/framework/settings.py                     | 12 +++\n 3 files changed, 109 insertions(+)\n create mode 100644 dts/framework/remote_session/__init__.py\n create mode 100644 dts/framework/remote_session/remote_session.py",
    "diff": "diff --git a/dts/framework/remote_session/__init__.py b/dts/framework/remote_session/__init__.py\nnew file mode 100644\nindex 0000000000..9bb042a482\n--- /dev/null\n+++ b/dts/framework/remote_session/__init__.py\n@@ -0,0 +1,2 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2022 PANTHEON.tech s.r.o.\ndiff --git a/dts/framework/remote_session/remote_session.py b/dts/framework/remote_session/remote_session.py\nnew file mode 100644\nindex 0000000000..33047d9d0a\n--- /dev/null\n+++ b/dts/framework/remote_session/remote_session.py\n@@ -0,0 +1,95 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2010-2014 Intel Corporation\n+# Copyright(c) 2022 PANTHEON.tech s.r.o.\n+# Copyright(c) 2022 University of New Hampshire\n+\n+import dataclasses\n+from abc import ABC, abstractmethod\n+\n+from framework.config import NodeConfiguration\n+from framework.logger import DTSLOG\n+from framework.settings import SETTINGS\n+\n+\n+@dataclasses.dataclass(slots=True, frozen=True)\n+class HistoryRecord:\n+    name: str\n+    command: str\n+    output: str | int\n+\n+\n+class RemoteSession(ABC):\n+    name: str\n+    hostname: str\n+    ip: str\n+    port: int | None\n+    username: str\n+    password: str\n+    logger: DTSLOG\n+    history: list[HistoryRecord]\n+    _node_config: NodeConfiguration\n+\n+    def __init__(\n+        self,\n+        node_config: NodeConfiguration,\n+        session_name: str,\n+        logger: DTSLOG,\n+    ):\n+        self._node_config = node_config\n+\n+        self.name = session_name\n+        self.hostname = node_config.hostname\n+        self.ip = self.hostname\n+        self.port = None\n+        if \":\" in self.hostname:\n+            self.ip, port = self.hostname.split(\":\")\n+            self.port = int(port)\n+        self.username = node_config.user\n+        self.password = node_config.password or \"\"\n+        self.logger = logger\n+        self.history = []\n+\n+        self.logger.info(f\"Connecting to {self.username}@{self.hostname}.\")\n+        self._connect()\n+        self.logger.info(f\"Connection to {self.username}@{self.hostname} successful.\")\n+\n+    @abstractmethod\n+    def _connect(self) -> None:\n+        \"\"\"\n+        Create connection to assigned node.\n+        \"\"\"\n+        pass\n+\n+    def send_command(self, command: str, timeout: float = SETTINGS.timeout) -> str:\n+        self.logger.info(f\"Sending: {command}\")\n+        out = self._send_command(command, timeout)\n+        self.logger.debug(f\"Received from {command}: {out}\")\n+        self._history_add(command=command, output=out)\n+        return out\n+\n+    @abstractmethod\n+    def _send_command(self, command: str, timeout: float) -> str:\n+        \"\"\"\n+        Send a command and return the output.\n+        \"\"\"\n+\n+    def _history_add(self, command: str, output: str) -> None:\n+        self.history.append(\n+            HistoryRecord(name=self.name, command=command, output=output)\n+        )\n+\n+    def close(self, force: bool = False) -> None:\n+        self.logger.logger_exit()\n+        self._close(force)\n+\n+    @abstractmethod\n+    def _close(self, force: bool = False) -> None:\n+        \"\"\"\n+        Close the remote session, freeing all used resources.\n+        \"\"\"\n+\n+    @abstractmethod\n+    def is_alive(self) -> bool:\n+        \"\"\"\n+        Check whether the session is still responding.\n+        \"\"\"\ndiff --git a/dts/framework/settings.py b/dts/framework/settings.py\nindex b6c5bba2b9..800f2c7b7f 100644\n--- a/dts/framework/settings.py\n+++ b/dts/framework/settings.py\n@@ -58,6 +58,7 @@ def __call__(\n class _Settings:\n     config_file_path: str\n     output_dir: str\n+    timeout: float\n     verbose: bool\n \n \n@@ -82,6 +83,16 @@ def _get_parser() -> argparse.ArgumentParser:\n         help=\"[DTS_OUTPUT_DIR] Output directory where dts logs and results are saved.\",\n     )\n \n+    parser.add_argument(\n+        \"-t\",\n+        \"--timeout\",\n+        action=_env_arg(\"DTS_TIMEOUT\"),\n+        default=15,\n+        required=False,\n+        help=\"[DTS_TIMEOUT] The default timeout for all DTS operations except for \"\n+        \"compiling DPDK.\",\n+    )\n+\n     parser.add_argument(\n         \"-v\",\n         \"--verbose\",\n@@ -100,6 +111,7 @@ def _get_settings() -> _Settings:\n     return _Settings(\n         config_file_path=parsed_args.config_file,\n         output_dir=parsed_args.output_dir,\n+        timeout=float(parsed_args.timeout),\n         verbose=(parsed_args.verbose == \"Y\"),\n     )\n \n",
    "prefixes": [
        "v7",
        "5/9"
    ]
}