From b389c3c4510b29cb13c64a9cf14093edd6bed0e7 Mon Sep 17 00:00:00 2001 From: Lili Deng Date: Tue, 27 Aug 2024 15:16:36 +0800 Subject: [PATCH] support detect vmware esxi --- lisa/executable.py | 17 +++++++++++++++-- lisa/operating_system.py | 12 ++++++++++++ lisa/tools/lscpu.py | 41 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/lisa/executable.py b/lisa/executable.py index 46185465bf..9a085f533c 100644 --- a/lisa/executable.py +++ b/lisa/executable.py @@ -26,7 +26,6 @@ if TYPE_CHECKING: from lisa.node import Node - T = TypeVar("T") @@ -168,6 +167,10 @@ def create(cls, node: Node, *args: Any, **kwargs: Any) -> Tool: freebsd_tool = cls._freebsd_tool() if freebsd_tool: tool_cls = freebsd_tool + elif "VMWareESXi" in node.os.name: + vmware_esxi_tool = cls._vmware_esxi_tool() + if vmware_esxi_tool: + tool_cls = vmware_esxi_tool return tool_cls(node, *args, **kwargs) @classmethod @@ -184,11 +187,21 @@ def _freebsd_tool(cls) -> Optional[Type[Tool]]: """ return None + @classmethod + def _vmware_esxi_tool(cls) -> Optional[Type[Tool]]: + """ + return a vmware esxi version tool class, if it's needed + """ + return None + def command_exists(self, command: str) -> Tuple[bool, bool]: exists = False use_sudo = False if self.node.is_posix: - where_command = "command -v" + if "VMWareESXi" in self.node.os.name: + where_command = "which" + else: + where_command = "command -v" else: where_command = "where" where_command = f"{where_command} {command}" diff --git a/lisa/operating_system.py b/lisa/operating_system.py index b83d5b294b..5bb44da351 100644 --- a/lisa/operating_system.py +++ b/lisa/operating_system.py @@ -128,6 +128,9 @@ class OperatingSystem: __release_pattern = re.compile(r"^DISTRIB_ID='?([^ \n']+).*$", re.M) __suse_release_pattern = re.compile(r"^(SUSE).*$", re.M) __bmc_release_pattern = re.compile(r".*(wcscli).*$", re.M) + # VMware ESXi 8.0.2 build-23305546 + # VMware ESXi 8.0 Update 2 + __vmware_esxi_release_pattern = re.compile(r"^(VMware ESXi).*$", re.M) __posix_factory: Optional[Factory[Any]] = None @@ -250,6 +253,9 @@ def _get_detect_string(cls, node: Any) -> Iterable[str]: cmd_result = typed_node.execute(cmd="wcscli", no_error_log=True) yield get_matched_str(cmd_result.stdout, cls.__bmc_release_pattern) + cmd_result = typed_node.execute(cmd="vmware -lv", no_error_log=True) + yield get_matched_str(cmd_result.stdout, cls.__vmware_esxi_release_pattern) + # try best from distros'family through ID_LIKE yield get_matched_str( cmd_result_os_release.stdout, cls.__os_release_pattern_idlike @@ -681,6 +687,12 @@ def name_pattern(cls) -> Pattern[str]: return re.compile("^wcscli$") +class VMWareESXi(Posix): + @classmethod + def name_pattern(cls) -> Pattern[str]: + return re.compile("^VMware ESXi$") + + class MacOS(Posix): @classmethod def name_pattern(cls) -> Pattern[str]: diff --git a/lisa/tools/lscpu.py b/lisa/tools/lscpu.py index 88bc49463f..7f7bac8362 100644 --- a/lisa/tools/lscpu.py +++ b/lisa/tools/lscpu.py @@ -107,6 +107,10 @@ def command(self) -> str: def _windows_tool(cls) -> Optional[Type[Tool]]: return WindowsLscpu + @classmethod + def _vmware_esxi_tool(cls) -> Optional[Type[Tool]]: + return VMWareESXiLscpu + @classmethod def _freebsd_tool(cls) -> Optional[Type[Tool]]: return BSDLscpu @@ -438,3 +442,40 @@ def calculate_vcpu_count(self, force_run: bool = False) -> int: * self.get_cluster_count() * self.get_thread_per_core_count() ) + + +class VMWareESXiLscpu(Lscpu): + # CPU Threads: 208 + __cpu_threads = re.compile(r"CPU Threads:[ ]+([\d]+)?", re.M) + # CPU Packages: 2 + __cpu_packages = re.compile(r"CPU Packages:[ ]+([\d]+)?", re.M) + # CPU Cores: 104 + __cpu_cores = re.compile(r"CPU Cores:[ ]+([\d]+)?", re.M) + + @property + def command(self) -> str: + return "esxcli" + + def get_core_count(self, force_run: bool = False) -> int: + result = self.run("hardware cpu global get", force_run) + matched = self.__cpu_threads.findall(result.stdout) + assert_that( + len(matched), + f"cpu thread should have exact one line, but got {matched}", + ).is_equal_to(1) + self._core_count = int(matched[0]) + return self._core_count + + def calculate_vcpu_count(self, force_run: bool = False) -> int: + result = self.run("hardware cpu global get", force_run) + matched_cpu_packages = self.__cpu_packages.findall(result.stdout) + assert_that( + len(matched_cpu_packages), + f"cpu packages should have exact one line, but got {matched_cpu_packages}", + ).is_equal_to(1) + matched_cpu_cores = self.__cpu_cores.findall(result.stdout) + assert_that( + len(matched_cpu_cores), + f"cpu cores should have exact one line, but got {matched_cpu_cores}", + ).is_equal_to(1) + return int(matched_cpu_packages[0]) * int(matched_cpu_cores[0])