get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 127147,
    "url": "http://patchwork.dpdk.org/api/patches/127147/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dts/patch/20230522083117.8835-1-daxuex.gao@intel.com/",
    "project": {
        "id": 3,
        "url": "http://patchwork.dpdk.org/api/projects/3/?format=api",
        "name": "DTS",
        "link_name": "dts",
        "list_id": "dts.dpdk.org",
        "list_email": "dts@dpdk.org",
        "web_url": "",
        "scm_url": "git://dpdk.org/tools/dts",
        "webscm_url": "http://git.dpdk.org/tools/dts/",
        "list_archive_url": "https://inbox.dpdk.org/dts",
        "list_archive_url_format": "https://inbox.dpdk.org/dts/{}",
        "commit_url_format": ""
    },
    "msgid": "<20230522083117.8835-1-daxuex.gao@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dts/20230522083117.8835-1-daxuex.gao@intel.com",
    "date": "2023-05-22T08:31:17",
    "name": "[v2] framework: fix container vm port conflict",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "0fe9cf6a0f6817c8ce76db7b635febe84194176a",
    "submitter": {
        "id": 2427,
        "url": "http://patchwork.dpdk.org/api/people/2427/?format=api",
        "name": "Gao, DaxueX",
        "email": "daxuex.gao@intel.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.dpdk.org/project/dts/patch/20230522083117.8835-1-daxuex.gao@intel.com/mbox/",
    "series": [
        {
            "id": 28102,
            "url": "http://patchwork.dpdk.org/api/series/28102/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dts/list/?series=28102",
            "date": "2023-05-22T08:31:17",
            "name": "[v2] framework: fix container vm port conflict",
            "version": 2,
            "mbox": "http://patchwork.dpdk.org/series/28102/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/127147/comments/",
    "check": "success",
    "checks": "http://patchwork.dpdk.org/api/patches/127147/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dts-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 58F6D42B6F;\n\tMon, 22 May 2023 10:31:18 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 532B6410DD;\n\tMon, 22 May 2023 10:31:18 +0200 (CEST)",
            "from mga05.intel.com (mga05.intel.com [192.55.52.43])\n by mails.dpdk.org (Postfix) with ESMTP id 588A6410D1\n for <dts@dpdk.org>; Mon, 22 May 2023 10:31:17 +0200 (CEST)",
            "from orsmga005.jf.intel.com ([10.7.209.41])\n by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 22 May 2023 01:31:16 -0700",
            "from unknown (HELO localhost.localdomain) ([10.239.252.161])\n by orsmga005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 22 May 2023 01:31:14 -0700"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n d=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n t=1684744277; x=1716280277;\n h=from:to:cc:subject:date:message-id;\n bh=wcUYohRlesmnp4e2yAq17AdRoS4imngDXLvStg/avXQ=;\n b=cV7TJN0SBOiFxf9WGkqblizjIRvsJ3YZ1u/639ECw+eP659EIqO3g6Mz\n G574alHIIRF7kytRKR8Zr5e70qhGSwytiD2tExm4LXT9D467qa3I02qZ/\n JCvUDXPVD2M4xbeWo0bgUAcIsE2c7s3A7SZTSExAk8i5XrPXVlHXPshsw\n SdA1ew8/stDNAsglShQ20Iq/6JAblGUHH65ZVrGAiG8tjcOXlXsnR9stG\n RoWCGHckZrNM/sfoQMbvxxXM6x90s2zpFyxqpJe6xt7V7c6uBh3mBaQqj\n 7kn/+KvHg+49X2hnNA0baUecuD37uwwjO41d58Ogn1cu+0Je1W41l+JcY A==;",
        "X-IronPort-AV": [
            "E=McAfee;i=\"6600,9927,10717\"; a=\"439216156\"",
            "E=Sophos;i=\"6.00,183,1681196400\"; d=\"scan'208\";a=\"439216156\"",
            "E=McAfee;i=\"6600,9927,10717\"; a=\"877682387\"",
            "E=Sophos;i=\"6.00,183,1681196400\"; d=\"scan'208\";a=\"877682387\""
        ],
        "X-ExtLoop1": "1",
        "From": "Daxue Gao <daxuex.gao@intel.com>",
        "To": "dts@dpdk.org",
        "Cc": "Daxue Gao <daxuex.gao@intel.com>",
        "Subject": "[PATCH v2] framework: fix container vm port conflict",
        "Date": "Mon, 22 May 2023 16:31:17 +0800",
        "Message-Id": "<20230522083117.8835-1-daxuex.gao@intel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "X-BeenThere": "dts@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "test suite reviews and discussions <dts.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dts>,\n <mailto:dts-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dts/>",
        "List-Post": "<mailto:dts@dpdk.org>",
        "List-Help": "<mailto:dts-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dts>,\n <mailto:dts-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dts-bounces@dpdk.org"
    },
    "content": "Fix the problem that the container vm port conflict causes the vm to fail to start.\nCapture the port conflict by exception, and assign a new port number to start the vm.\nThe port conflict includes tcp forward/vnc/telnet/migrate port.\n\nSigned-off-by: Daxue Gao <daxuex.gao@intel.com>\n---\n framework/exception.py     | 12 ++++++++++++\n framework/qemu_kvm.py      | 25 ++++++++++++++++++++-----\n framework/virt_base.py     |  7 +++----\n framework/virt_resource.py | 12 ++++++------\n 4 files changed, 41 insertions(+), 15 deletions(-)",
    "diff": "diff --git a/framework/exception.py b/framework/exception.py\nindex fb0fa72e..e8659bd1 100644\n--- a/framework/exception.py\n+++ b/framework/exception.py\n@@ -146,3 +146,15 @@ class VirtVmOperationException(Exception):\n \n class VirtHostPrepareException(Exception):\n     pass\n+\n+\n+class VmPortConflictException(Exception):\n+    \"\"\"\n+    Start VM vnc port or vm port conflict failed.\n+    \"\"\"\n+\n+    def __init__(self, error):\n+        self.error = error\n+\n+    def __str__(self):\n+        pass\ndiff --git a/framework/qemu_kvm.py b/framework/qemu_kvm.py\nindex 0131abcc..b656675c 100644\n--- a/framework/qemu_kvm.py\n+++ b/framework/qemu_kvm.py\n@@ -6,7 +6,7 @@ import os\n import re\n import time\n \n-from .exception import StartVMFailedException\n+from .exception import StartVMFailedException, VmPortConflictException\n from .settings import DTS_PARALLEL_SETTING, get_host_ip, load_global_setting\n from .utils import RED, parallel_lock\n from .virt_base import ST_NOTSTART, ST_PAUSE, ST_RUNNING, ST_UNKNOWN, VirtBase\n@@ -1404,16 +1404,20 @@ class QEMUKvm(VirtBase):\n     @parallel_lock(num=4)\n     def __send_qemu_cmd(self, qemu_boot_line, dut_id):\n         # add more time for qemu start will be slow when system is busy\n-        ret = self.host_session.send_expect(\n-            qemu_boot_line, \"# \", verify=True, timeout=30\n-        )\n+        ret = self.host_session.send_expect(qemu_boot_line, \"# \", timeout=30)\n+        ret_status = int(self.host_session.send_expect(\"echo $?\", \"#\", timeout=30))\n \n         # record start time\n         self.start_time = time.time()\n \n         # wait for qemu process ready\n         time.sleep(2)\n-        if type(ret) is int and ret != 0:\n+        if type(ret_status) is int and ret_status != 0:\n+            if self.vm_port_conflict(ret):\n+                self.qemu_boot_line = \"\"\n+                self.pt_idx = 0\n+                delattr(self, \"hostfwd_addr\")\n+                raise VmPortConflictException(self)\n             raise StartVMFailedException(\"Start VM failed!!!\")\n \n     def _quick_start_vm(self):\n@@ -2043,3 +2047,14 @@ class QEMUKvm(VirtBase):\n             map = list(zip(threads, lcores))\n         for thread, lcore in map:\n             self.host_session.send_expect(\"taskset -pc %s %s\" % (lcore, thread), \"#\")\n+\n+    def vm_port_conflict(self, ret):\n+        \"\"\"\n+        check for vm port conflict\n+        \"\"\"\n+        status = None\n+        if \"Could not set up host forwarding rule\" in ret:\n+            status = True\n+        elif \"Failed to find an available port: Address already in use\" in ret:\n+            status = True\n+        return status\ndiff --git a/framework/virt_base.py b/framework/virt_base.py\nindex 24f50d0f..e8c34b09 100644\n--- a/framework/virt_base.py\n+++ b/framework/virt_base.py\n@@ -279,6 +279,7 @@ class VirtBase(object):\n         \"\"\"\n         Start VM and instantiate the VM with VirtDut.\n         \"\"\"\n+        vm_dut = None\n         try:\n             if load_config is True:\n                 self.load_config()\n@@ -293,9 +294,8 @@ class VirtBase(object):\n                 vm_dut = self.instantiate_vm_dut(\n                     set_target, cpu_topo, bind_dev=bind_dev, autodetect_topo=True\n                 )\n-            else:\n-                vm_dut = None\n-\n+        except exception.VmPortConflictException:\n+            vm_dut = self.start()\n         except Exception as vm_except:\n             if self.handle_exception(vm_except):\n                 print(utils.RED(\"Handled exception \" + str(type(vm_except))))\n@@ -305,7 +305,6 @@ class VirtBase(object):\n             if callable(self.callback):\n                 self.callback()\n \n-            return None\n         return vm_dut\n \n     def quick_start(self, load_config=True, set_target=True, cpu_topo=\"\"):\ndiff --git a/framework/virt_resource.py b/framework/virt_resource.py\nindex 3bc4b87b..231cdebc 100644\n--- a/framework/virt_resource.py\n+++ b/framework/virt_resource.py\n@@ -2,7 +2,7 @@\n # Copyright(c) 2010-2015 Intel Corporation\n #\n \n-from random import randint\n+from random import randint, randrange\n \n from .utils import RED, get_obj_funcs, parallel_lock\n \n@@ -344,15 +344,15 @@ class VirtResource(object):\n         if vm == \"\":\n             print(\"Alloc host port request vitual machine name!!!\")\n             return None\n-\n+        offset = randrange(0, 1000, 200)\n         if port_type == \"connect\":\n-            port = INIT_FREE_PORT\n+            port = INIT_FREE_PORT + offset\n         elif port_type == \"serial\":\n-            port = INIT_SERIAL_PORT\n+            port = INIT_SERIAL_PORT + offset\n         elif port_type == \"migrate\":\n-            port = INIT_MIGRATE_PORT\n+            port = INIT_MIGRATE_PORT + offset\n         elif port_type == \"display\":\n-            port = INIT_DISPLAY_PORT + 5900\n+            port = INIT_DISPLAY_PORT + 5900 + offset\n \n         while True:\n             if (\n",
    "prefixes": [
        "v2"
    ]
}