[v1] framework: fix container vm port conflict

Message ID 20230522081016.6430-1-daxuex.gao@intel.com (mailing list archive)
State Superseded
Headers
Series [v1] framework: fix container vm port conflict |

Checks

Context Check Description
ci/Intel-dts-format-test fail Testing issues
ci/Intel-dts-pylama-test success Testing OK
ci/Intel-dts-suite-test success Testing OK

Commit Message

Gao, DaxueX May 22, 2023, 8:10 a.m. UTC
  Fix the problem that the container vm port conflict causes the vm to fail to start.
Capture the port conflict by exception, and assign a new port number to start the vm.
The port conflict includes tcp forward/vnc/telnet/migrate port.

Signed-off-by: Daxue Gao <daxuex.gao@intel.com>
---
 framework/exception.py     | 11 +++++++++++
 framework/qemu_kvm.py      | 25 ++++++++++++++++++++-----
 framework/virt_base.py     |  7 +++----
 framework/virt_resource.py | 12 ++++++------
 4 files changed, 40 insertions(+), 15 deletions(-)
  

Patch

diff --git a/framework/exception.py b/framework/exception.py
index fb0fa72e..09012d43 100644
--- a/framework/exception.py
+++ b/framework/exception.py
@@ -146,3 +146,14 @@  class VirtVmOperationException(Exception):
 
 class VirtHostPrepareException(Exception):
     pass
+
+
+class VmPortConflictException(Exception):
+    """
+    Start VM vnc port or vm port conflict failed.
+    """
+    def __init__(self, error):
+        self.error = error
+
+    def __str__(self):
+        pass
diff --git a/framework/qemu_kvm.py b/framework/qemu_kvm.py
index 0131abcc..b656675c 100644
--- a/framework/qemu_kvm.py
+++ b/framework/qemu_kvm.py
@@ -6,7 +6,7 @@  import os
 import re
 import time
 
-from .exception import StartVMFailedException
+from .exception import StartVMFailedException, VmPortConflictException
 from .settings import DTS_PARALLEL_SETTING, get_host_ip, load_global_setting
 from .utils import RED, parallel_lock
 from .virt_base import ST_NOTSTART, ST_PAUSE, ST_RUNNING, ST_UNKNOWN, VirtBase
@@ -1404,16 +1404,20 @@  class QEMUKvm(VirtBase):
     @parallel_lock(num=4)
     def __send_qemu_cmd(self, qemu_boot_line, dut_id):
         # add more time for qemu start will be slow when system is busy
-        ret = self.host_session.send_expect(
-            qemu_boot_line, "# ", verify=True, timeout=30
-        )
+        ret = self.host_session.send_expect(qemu_boot_line, "# ", timeout=30)
+        ret_status = int(self.host_session.send_expect("echo $?", "#", timeout=30))
 
         # record start time
         self.start_time = time.time()
 
         # wait for qemu process ready
         time.sleep(2)
-        if type(ret) is int and ret != 0:
+        if type(ret_status) is int and ret_status != 0:
+            if self.vm_port_conflict(ret):
+                self.qemu_boot_line = ""
+                self.pt_idx = 0
+                delattr(self, "hostfwd_addr")
+                raise VmPortConflictException(self)
             raise StartVMFailedException("Start VM failed!!!")
 
     def _quick_start_vm(self):
@@ -2043,3 +2047,14 @@  class QEMUKvm(VirtBase):
             map = list(zip(threads, lcores))
         for thread, lcore in map:
             self.host_session.send_expect("taskset -pc %s %s" % (lcore, thread), "#")
+
+    def vm_port_conflict(self, ret):
+        """
+        check for vm port conflict
+        """
+        status = None
+        if "Could not set up host forwarding rule" in ret:
+            status = True
+        elif "Failed to find an available port: Address already in use" in ret:
+            status = True
+        return status
diff --git a/framework/virt_base.py b/framework/virt_base.py
index 24f50d0f..e8c34b09 100644
--- a/framework/virt_base.py
+++ b/framework/virt_base.py
@@ -279,6 +279,7 @@  class VirtBase(object):
         """
         Start VM and instantiate the VM with VirtDut.
         """
+        vm_dut = None
         try:
             if load_config is True:
                 self.load_config()
@@ -293,9 +294,8 @@  class VirtBase(object):
                 vm_dut = self.instantiate_vm_dut(
                     set_target, cpu_topo, bind_dev=bind_dev, autodetect_topo=True
                 )
-            else:
-                vm_dut = None
-
+        except exception.VmPortConflictException:
+            vm_dut = self.start()
         except Exception as vm_except:
             if self.handle_exception(vm_except):
                 print(utils.RED("Handled exception " + str(type(vm_except))))
@@ -305,7 +305,6 @@  class VirtBase(object):
             if callable(self.callback):
                 self.callback()
 
-            return None
         return vm_dut
 
     def quick_start(self, load_config=True, set_target=True, cpu_topo=""):
diff --git a/framework/virt_resource.py b/framework/virt_resource.py
index 3bc4b87b..231cdebc 100644
--- a/framework/virt_resource.py
+++ b/framework/virt_resource.py
@@ -2,7 +2,7 @@ 
 # Copyright(c) 2010-2015 Intel Corporation
 #
 
-from random import randint
+from random import randint, randrange
 
 from .utils import RED, get_obj_funcs, parallel_lock
 
@@ -344,15 +344,15 @@  class VirtResource(object):
         if vm == "":
             print("Alloc host port request vitual machine name!!!")
             return None
-
+        offset = randrange(0, 1000, 200)
         if port_type == "connect":
-            port = INIT_FREE_PORT
+            port = INIT_FREE_PORT + offset
         elif port_type == "serial":
-            port = INIT_SERIAL_PORT
+            port = INIT_SERIAL_PORT + offset
         elif port_type == "migrate":
-            port = INIT_MIGRATE_PORT
+            port = INIT_MIGRATE_PORT + offset
         elif port_type == "display":
-            port = INIT_DISPLAY_PORT + 5900
+            port = INIT_DISPLAY_PORT + 5900 + offset
 
         while True:
             if (