[V1] framework: add docker container support

Message ID 20221227055111.11097-1-daxuex.gao@intel.com (mailing list archive)
State Accepted
Headers
Series [V1] framework: add docker container support |

Checks

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

Commit Message

Gao, DaxueX Dec. 27, 2022, 5:51 a.m. UTC
  1.Remove commands which are not in container, such as: modprobe, lsmod.
2.Remove kernel build when building dpdk in the container.
3.Add checking mount hugepage in the container, and fixing failures for hugepages configure.
4.Judge by the environment variable CONTAINER, the storage overlay and the return value of the execution system command, it is a container.
5.Fix vm mapping port issue with ssh port is not 22.
 When crb uses a non-22 port, then start VM, 
 the mapping will be converted to dutIP:port:host_port to vm 22 port,
 such as 127.0.0.1:5000:600 --> vm:22, which cannot be mapped. 
 so change it to dutIP:host_port to vm 22 port.

Signed-off-by: Daxue Gao <daxuex.gao@intel.com>
Signed-off-by: Lijuan Tu <lijuan.tu@intel.com>
---
 framework/crb.py          | 30 +++++++++++++++++++++--
 framework/dut.py          |  3 ++-
 framework/project_dpdk.py | 50 +++++++++++++++++++++++----------------
 framework/qemu_kvm.py     | 12 +++++++---
 framework/qemu_libvirt.py | 11 +++++++--
 framework/tester.py       |  9 +++----
 framework/virt_base.py    |  2 ++
 7 files changed, 84 insertions(+), 33 deletions(-)
  

Comments

Tu, Lijuan Jan. 4, 2023, 12:59 a.m. UTC | #1
On Tue, 27 Dec 2022 13:51:11 +0800, Daxue Gao <daxuex.gao@intel.com> wrote:
> 1.Remove commands which are not in container, such as: modprobe, lsmod.
> 2.Remove kernel build when building dpdk in the container.
> 3.Add checking mount hugepage in the container, and fixing failures for hugepages configure.
> 4.Judge by the environment variable CONTAINER, the storage overlay and the return value of the execution system command, it is a container.
> 5.Fix vm mapping port issue with ssh port is not 22.
>  When crb uses a non-22 port, then start VM, 
>  the mapping will be converted to dutIP:port:host_port to vm 22 port,
>  such as 127.0.0.1:5000:600 --> vm:22, which cannot be mapped. 
>  so change it to dutIP:host_port to vm 22 port.
> 
> Signed-off-by: Daxue Gao <daxuex.gao@intel.com>
> Signed-off-by: Lijuan Tu <lijuan.tu@intel.com>

Reviewed-by: Lijuan Tu <lijuan.tu@intel.com>
Applied, thanks
  

Patch

diff --git a/framework/crb.py b/framework/crb.py
index 3c93fdc4..48526ac1 100644
--- a/framework/crb.py
+++ b/framework/crb.py
@@ -62,6 +62,7 @@  class Crb(object):
             self.alt_session.init_log(self.logger)
         else:
             self.alt_session = None
+        self.is_container = self._is_container()
 
     def get_ip_address(self):
         """
@@ -211,8 +212,20 @@  class Crb(object):
         out = out.strip(" [PEXPECT]#")
         # only mount hugepage when no hugetlbfs mounted
         if not len(out):
-            self.send_expect("mkdir -p /mnt/huge", "# ")
-            self.send_expect("mount -t hugetlbfs nodev /mnt/huge", "# ")
+            if self.is_container:
+                raise ValueError(
+                    "container hugepage not mount, please check hugepage config"
+                )
+            else:
+                self.send_expect("mkdir -p /mnt/huge", "# ")
+                self.send_expect("mount -t hugetlbfs nodev /mnt/huge", "# ")
+                out = self.send_expect(
+                    "awk '/hugetlbfs/ { print $2 }' /proc/mounts", "# "
+                )
+                if not len(out.strip(" [PEXPECT]#")):
+                    raise ValueError(
+                        "hugepage config error, please check hugepage config"
+                    )
 
     def strip_hugepage_path(self):
         mounts = self.send_expect("cat /proc/mounts |grep hugetlbfs", "# ")
@@ -1035,3 +1048,16 @@  class Crb(object):
         link_status_matcher = r"Link detected: (\w+)"
         link_status = re.search(link_status_matcher, out).groups()[0]
         return "Up" if link_status == "yes" else "Down"
+
+    def _is_container(self):
+        if self.send_expect("export |grep -i CONTAINER ", "# "):
+            return True
+        elif self.send_expect("df -h / |grep overlay ", "# "):
+            return True
+        elif self.send_expect(
+            "systemd-detect-virt -c|egrep '(systemd-nspawn|lxc|docker|podman|rkt|wsl|container-other)$' ",
+            "# ",
+        ):
+            return True
+        else:
+            return False
diff --git a/framework/dut.py b/framework/dut.py
index b8c01f47..481c0cb6 100644
--- a/framework/dut.py
+++ b/framework/dut.py
@@ -423,7 +423,8 @@  class Dut(Crb):
                     timeout=30,
                 )
                 # bind to linux kernel driver
-                self.send_expect("modprobe %s" % driver, "# ")
+                if not self.is_container:
+                    self.send_expect("modprobe %s" % driver, "# ")
                 self.send_expect(
                     "echo %s > /sys/bus/pci/drivers/%s/bind" % (pci_bus, driver), "# "
                 )
diff --git a/framework/project_dpdk.py b/framework/project_dpdk.py
index c20aa044..3f34ee02 100644
--- a/framework/project_dpdk.py
+++ b/framework/project_dpdk.py
@@ -87,11 +87,12 @@  class DPDKdut(Dut):
 
     def setup_modules_linux(self, target, drivername, drivermode):
         if drivername == "vfio-pci":
-            self.send_expect("rmmod vfio_pci", "#")
-            self.send_expect("rmmod vfio_iommu_type1", "#")
-            self.send_expect("rmmod vfio", "#")
-            self.send_expect("modprobe vfio", "#")
-            self.send_expect("modprobe vfio-pci", "#")
+            if not self.is_container:
+                self.send_expect("rmmod vfio_pci", "#")
+                self.send_expect("rmmod vfio_iommu_type1", "#")
+                self.send_expect("rmmod vfio", "#")
+                self.send_expect("modprobe vfio", "#")
+                self.send_expect("modprobe vfio-pci", "#")
             if drivermode == "noiommu":
                 self.send_expect(
                     "echo 1 > /sys/module/vfio/parameters/enable_unsafe_noiommu_mode",
@@ -263,26 +264,32 @@  class DPDKdut(Dut):
             self.send_expect("export PKG_CONFIG_LIBDIR=%s" % pkg_path, "# ")
 
         self.send_expect("rm -rf " + target, "#")
-        out = self.send_expect(
-            "CC=%s meson -Denable_kmods=True -Dlibdir=lib %s --default-library=%s %s"
-            % (toolchain, extra_options, default_library, target),
-            "[~|~\]]# ",
-            build_time,
-        )
+        if self.is_container:
+            meson_build_cmd = (
+                "CC=%s meson -Denable_kmods=False -Dlibdir=lib %s --default-library=%s %s"
+                % (toolchain, extra_options, default_library, target)
+            )
+        else:
+            meson_build_cmd = (
+                "CC=%s meson -Denable_kmods=True -Dlibdir=lib %s --default-library=%s %s"
+                % (toolchain, extra_options, default_library, target)
+            )
+        out = self.send_expect(meson_build_cmd, "[~|~\]]# ", build_time)
         assert "FAILED" not in out, "meson setup failed ..."
 
         out = self.send_expect("ninja -C %s" % target, "[~|~\]]# ", build_time)
         assert "FAILED" not in out, "ninja complie failed ..."
 
         # copy kmod file to the folder same as make
-        out = self.send_expect(
-            "find ./%s/kernel/ -name *.ko" % target, "# ", verify=True
-        )
-        self.send_expect("mkdir -p %s/kmod" % target, "# ")
-        if not isinstance(out, int) and len(out) > 0:
-            kmod = out.split("\r\n")
-            for mod in kmod:
-                self.send_expect("cp %s %s/kmod/" % (mod, target), "# ")
+        if not self.is_container:
+            out = self.send_expect(
+                "find ./%s/kernel/ -name *.ko" % target, "# ", verify=True
+            )
+            self.send_expect("mkdir -p %s/kmod" % target, "# ")
+            if not isinstance(out, int) and len(out) > 0:
+                kmod = out.split("\r\n")
+                for mod in kmod:
+                    self.send_expect("cp %s %s/kmod/" % (mod, target), "# ")
 
     def build_install_dpdk_freebsd_meson(self, target, extra_options):
         # meson build same as linux
@@ -342,7 +349,7 @@  class DPDKdut(Dut):
                     self.session.copy_file_to("dep/" + p, dst_dir)
 
             # copy QMP file to dut
-            if ":" not in self.session.name:
+            if "virtdut" not in self.session.name:
                 out = self.send_expect("ls -d ~/QMP", "# ", verify=True)
                 if isinstance(out, int):
                     self.send_expect("mkdir -p ~/QMP", "# ")
@@ -575,7 +582,8 @@  class DPDKtester(Tester):
             out = self.send_expect("tar zxfm tclclient.tgz", "# ")
             assert "Error" not in out
 
-        self.send_expect("modprobe uio", "# ")
+        if not self.is_container:
+            self.send_expect("modprobe uio", "# ")
 
         self.tester_prerequisites()
 
diff --git a/framework/qemu_kvm.py b/framework/qemu_kvm.py
index dd8e7857..0131abcc 100644
--- a/framework/qemu_kvm.py
+++ b/framework/qemu_kvm.py
@@ -244,6 +244,11 @@  class QEMUKvm(VirtBase):
         else:
             self.host_logger.warning("Hardware virtualization disabled on host!!!")
             return False
+        if self.host_is_container:
+            if self.host_session.send_expect("ls /dev/kvm || ls /sys/module/kvm", "# "):
+                return True
+            else:
+                return False
 
         out = self.host_session.send_expect("lsmod | grep kvm", "# ")
         if "kvm" in out and "kvm_intel" in out:
@@ -256,8 +261,9 @@  class QEMUKvm(VirtBase):
         """
         Load the virtual module of kernel to enable the virtual ability.
         """
-        self.host_session.send_expect("modprobe kvm", "# ")
-        self.host_session.send_expect("modprobe kvm_intel", "# ")
+        if not self.host_is_container:
+            self.host_session.send_expect("modprobe kvm", "# ")
+            self.host_session.send_expect("modprobe kvm_intel", "# ")
         return True
 
     def disk_image_is_ok(self, image):
@@ -596,7 +602,7 @@  class QEMUKvm(VirtBase):
         host_addr = field(opt_hostfwd, 1)
         if not host_addr:
             addr = str(self.host_dut.get_ip_address())
-            host_addr = get_host_ip(addr)
+            host_addr = get_host_ip(addr).split(":")[0]
 
         # get the host port in the option
         host_port = field(opt_hostfwd, 2).split("-")[0]
diff --git a/framework/qemu_libvirt.py b/framework/qemu_libvirt.py
index cf406bad..e99ce8fb 100644
--- a/framework/qemu_libvirt.py
+++ b/framework/qemu_libvirt.py
@@ -106,6 +106,12 @@  class LibvirtKvm(VirtBase):
             self.host_logger.warning("Hardware virtualization " "disabled on host!!!")
             return False
 
+        if self.host_is_container:
+            if self.host_session.send_expect("ls /dev/kvm || ls /sys/module/kvm"):
+                return True
+            else:
+                return False
+
         out = self.host_session.send_expect("lsmod | grep kvm", "# ")
         if "kvm" not in out or "kvm_intel" not in out:
             return False
@@ -117,8 +123,9 @@  class LibvirtKvm(VirtBase):
         return True
 
     def load_virtual_mod(self):
-        self.host_session.send_expect("modprobe kvm", "# ")
-        self.host_session.send_expect("modprobe kvm_intel", "# ")
+        if not self.host_is_container:
+            self.host_session.send_expect("modprobe kvm", "# ")
+            self.host_session.send_expect("modprobe kvm_intel", "# ")
 
     def unload_virtual_mod(self):
         self.host_session.send_expect("rmmod kvm_intel", "# ")
diff --git a/framework/tester.py b/framework/tester.py
index 9a228f14..89f654d4 100644
--- a/framework/tester.py
+++ b/framework/tester.py
@@ -312,10 +312,11 @@  class Tester(Crb):
         if self.skip_setup:
             return
 
-        self.send_expect("modprobe igb", "# ", 20)
-        self.send_expect("modprobe ixgbe", "# ", 20)
-        self.send_expect("modprobe e1000e", "# ", 20)
-        self.send_expect("modprobe e1000", "# ", 20)
+        if not self.is_container:
+            self.send_expect("modprobe igb", "# ", 20)
+            self.send_expect("modprobe ixgbe", "# ", 20)
+            self.send_expect("modprobe e1000e", "# ", 20)
+            self.send_expect("modprobe e1000", "# ", 20)
 
         try:
             for (pci_bus, pci_id) in self.pci_devices_info:
diff --git a/framework/virt_base.py b/framework/virt_base.py
index a7fc8c4e..24f50d0f 100644
--- a/framework/virt_base.py
+++ b/framework/virt_base.py
@@ -55,6 +55,8 @@  class VirtBase(object):
         # init the host resource pool for VM
         self.virt_pool = self.host_dut.virt_pool
 
+        self.host_is_container = dut.is_container
+
         if not self.has_virtual_ability():
             if not self.enable_virtual_ability():
                 raise Exception("Dut [ %s ] cannot have the virtual ability!!!")