From patchwork Tue Dec 27 05:51:11 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gao, DaxueX" X-Patchwork-Id: 121399 Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id 2C2B5A04FD; Tue, 27 Dec 2022 07:07:23 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 21615410FC; Tue, 27 Dec 2022 07:07:23 +0100 (CET) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mails.dpdk.org (Postfix) with ESMTP id 87A7940E2D for ; Tue, 27 Dec 2022 07:07:21 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1672121241; x=1703657241; h=from:to:cc:subject:date:message-id; bh=KtCjfy+KFiAdA9PUjpvRWQdgNtdduFFOeDTTU2UWvhQ=; b=lODQ61Y/+E0ezfM10mgXInOOWEP6g1VKGg21mo8ILk3lQuLozYGtTkpT 6AZJR+igT3rNnSL3pGdMLCoDnvZYYPwmnlKtYcKKcHsV/GHppU3CCduvi GXdw0CLlr9AYw8Et0gDglwgt8Cnm87gWsu6Wjpoe8gz8J7+a48F9l16xx paJaECLoWS1qmgYlO92Yf/lhIBMB1IGN42KMLaiMDilxvObHpT7PQCW6a dBWU/r35x0rQKJUzJyj1v9ghkESBK2B6W303VIfyZCpPjM+WGI9c7IaS0 os7HDDL80lxHDmYx3R8Iq2/5fJrmLRomVl4L3hgHkeK5h63detx8jpHDw Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10572"; a="304152506" X-IronPort-AV: E=Sophos;i="5.96,277,1665471600"; d="scan'208";a="304152506" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Dec 2022 22:07:20 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10572"; a="760234870" X-IronPort-AV: E=Sophos;i="5.96,277,1665471600"; d="scan'208";a="760234870" Received: from unknown (HELO localhost.localdomain) ([10.239.252.161]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Dec 2022 22:07:16 -0800 From: Daxue Gao To: dts@dpdk.org Cc: lijuan.tu@intel.com, qingx.sun@intel.com, Daxue Gao Subject: [V1] framework: add docker container support Date: Tue, 27 Dec 2022 13:51:11 +0800 Message-Id: <20221227055111.11097-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 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dts-bounces@dpdk.org 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 Signed-off-by: Lijuan Tu Reviewed-by: Lijuan Tu --- 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(-) 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!!!")