From 3e2b3a3f3df7f04902b3ad27cb9d045607685e88 Mon Sep 17 00:00:00 2001 From: Dehan Meng Date: Thu, 12 Dec 2024 16:46:35 +0800 Subject: [PATCH] win_guest_debugging_tool: Support new feature for first case win_guest_debugging_tool is a new feature for windows guest to gather a wide range of information. including system configuration event logs, drivers, registry settings, update logs, services, uptime, processes, installed applications,network configuration installed KBs (knowledge base articleand optionally, memory dumps It's a powershell script is designed for comprehensive system diagnostics. So the first case is just run the script and checkout the output files whether are exact same with official doc. Signed-off-by: Dehan Meng --- qemu/tests/cfg/win_guest_debugging_tool.cfg | 22 ++ qemu/tests/win_guest_debugging_tool.py | 252 ++++++++++++++++++++ 2 files changed, 274 insertions(+) create mode 100644 qemu/tests/cfg/win_guest_debugging_tool.cfg create mode 100644 qemu/tests/win_guest_debugging_tool.py diff --git a/qemu/tests/cfg/win_guest_debugging_tool.cfg b/qemu/tests/cfg/win_guest_debugging_tool.cfg new file mode 100644 index 0000000000..8bfd610800 --- /dev/null +++ b/qemu/tests/cfg/win_guest_debugging_tool.cfg @@ -0,0 +1,22 @@ +- win_guest_debugging_tool: install setup image_copy unattended_install.cdrom + only Windows + type = win_guest_debugging_tool + tmp_dir = %TEMP% + runtimeout = 360 + shutdown_command = "shutdown -s -t 0" + reboot_command = "shutdown -r -t 0" + cmd_unrestrict_policy = 'powershell.exe Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process -Force' + test_tmp_dir = "%TEMP%\testtmpdir" + cmd_create_dir = "mkdir %s >nul 2>&1" + cmd_remove_dir = "rmdir /S /Q %s" + cdroms += " virtio" + cdrom_virtio = isos/windows/virtio-win.iso + cmd_findstr_in_file = type %s | findstr "%s" + include_sensitive_data = False + target_files = "msinfo32.txt,system.evtx,security.evtx,application.evtx,drv_list.csv,virtio_disk.txt,WindowsUpdate.log,Services.csv,WindowsUptime.txt,RunningProcesses.csv,InstalledApplications.csv,InstalledKBs.csv,NetworkInterfaces.txt,IPConfiguration.txt,setupapi.dev.log,setupapi.setup.log,setupapi.offline.log,ErrorWindowsUpdate.log,OutputWindowsUpdate.log,LocaleMetaData" + target_dump_files = "MEMORY.DMP,Minidump" + script_name = "CollectSystemInfo.ps1" + cmd_search_file_global = powershell.exe -Command "Get-PSDrive -PSProvider FileSystem | ForEach-Object { Get-ChildItem -Path $_.Root -Recurse -Filter '%s' -ErrorAction SilentlyContinue } | ForEach-Object { Join-Path -Path $_.Directory.FullName -ChildPath $_.Name }" + variants: + - check_script_execution: + windegtool_check_type = script_execution diff --git a/qemu/tests/win_guest_debugging_tool.py b/qemu/tests/win_guest_debugging_tool.py new file mode 100644 index 0000000000..fda47c2cb7 --- /dev/null +++ b/qemu/tests/win_guest_debugging_tool.py @@ -0,0 +1,252 @@ +import logging +import time +import os +import re +import base64 +import random +import string +import json +import threading + +import aexpect + +from distutils.util import strtobool +from avocado.utils import genio +from avocado.utils import path as avo_path +from avocado.utils import process +from avocado.core import exceptions +from aexpect.exceptions import ShellTimeoutError + +from virttest import error_context +from virttest import guest_agent +from virttest import utils_misc +from virttest import utils_disk +from virttest import env_process +from virttest import utils_net +from virttest import data_dir +from virttest import storage +from virttest import qemu_migration +from virttest.utils_version import VersionInterval + +from virttest.utils_windows import virtio_win +from provider.win_driver_installer_test import (uninstall_gagent, + run_installer_with_interaction) + +LOG_JOB = logging.getLogger('avocado.test') + + +class BaseVirtTest(object): + + def __init__(self, test, params, env): + self.test = test + self.params = params + self.env = env + + def initialize(self, test, params, env): + if test: + self.test = test + if params: + self.params = params + if env: + self.env = env + start_vm = self.params["start_vm"] + self.start_vm = start_vm + if self.start_vm == "yes": + vm = self.env.get_vm(params["main_vm"]) + vm.verify_alive() + self.vm = vm + + def setup(self, test, params, env): + if test: + self.test = test + if params: + self.params = params + if env: + self.env = env + + def run_once(self, test, params, env): + if test: + self.test = test + if params: + self.params = params + if env: + self.env = env + + def before_run_once(self, test, params, env): + pass + + def after_run_once(self, test, params, env): + pass + + def cleanup(self, test, params, env): + pass + + def execute(self, test, params, env): + self.initialize(test, params, env) + self.setup(test, params, env) + try: + self.before_run_once(test, params, env) + self.run_once(test, params, env) + self.after_run_once(test, params, env) + finally: + self.cleanup(test, params, env) + + +class WinDebugToolTest(BaseVirtTest): + def __init__(self, test, params, env): + super().__init__(test, params, env) + self._open_session_list = [] + self.vm = None + self.script_dir = None + self.script_name = params.get("script_name", "") # Assuming script is named CollectSystemInfo.ps1 + self.script_path = params.get("script_path", "") + self.tmp_dir = params.get("test_tmp_dir", "") + + def _get_session(self, params, vm): + if not vm: + vm = self.vm + vm.verify_alive() + timeout = int(params.get("login_timeout", 360)) + session = vm.wait_for_login(timeout=timeout) + return session + + def _cleanup_open_session(self): + try: + for s in self._open_session_list: + if s: + s.close() + except Exception: + pass + + def run_once(self, test, params, env): + BaseVirtTest.run_once(self, test, params, env) + if self.start_vm == "yes": + pass + + def cleanup(self, test, params, env): + self._cleanup_open_session() + + @error_context.context_aware + def setup(self, test, params, env): + BaseVirtTest.setup(self, test, params, env) + if self.start_vm == "yes": + session = self._get_session(params, self.vm) + self._open_session_list.append(session) + + error_context.context("Check whether debug tool exists.", LOG_JOB.info) + cmd_get_debug_tool_script = params['cmd_search_file_global'] % self.script_name + script_path = str(session.cmd_output(cmd_get_debug_tool_script, timeout=360)).strip() + print("script_path: %s\n" % script_path) + if script_path: + self.script_path = script_path + self.script_dir = self.script_path.replace(self.script_name, "").rstrip("\\") + self.script_path = "%TEMP%\CollectSystemInfo.ps1" + else: + test.error("The tool script file CollectSystemInfo.ps1 was not found. Please check.") + + error_context.context("Create tmp work dir since testing " + "would create lots of dir and files.", LOG_JOB.info) + session.cmd_output(params['cmd_create_dir'] % self.tmp_dir) + + def _check_generated_files(self, session, path, sensitive_data=False): + output = str(session.cmd_output(f"dir /b {path}")).strip() + print(output) + + target_files = ( + self.params["target_dump_files"] if sensitive_data + else self.params["target_files"] + ).split(',') + + for target_file in target_files: + if target_file not in output: + self.test.error(f"{target_file} is not included, please check it.") + + def _get_path(self, output, session, sensitive_data=False): + log_folder_path = re.search(r"Log folder path: (.+)", output).group(1) + self._check_generated_files(session, log_folder_path) + print(f"Log folder path: {log_folder_path}") + log_zip_path = f"{log_folder_path}.zip" + print(f"Log zip path: {log_zip_path}") + + if sensitive_data: + dump_folder_match = re.search(r"Dump folder path: (.+)", output) + if dump_folder_match: + dump_folder_path = dump_folder_match.group(1) + self._check_generated_files(session, dump_folder_path, sensitive_data=True) + print(f"Dump folder path: {dump_folder_path}") + dump_zip_path = f"{dump_folder_path}.zip" + print(f"Dump zip path: {dump_zip_path}") + return log_folder_path, log_zip_path, dump_folder_path, dump_zip_path + + return log_folder_path, log_zip_path + + +class WinDebugToolTestBasicCheck(WinDebugToolTest): + def __init__(self, test, params, env): + super().__init__(test, params, env) + + @error_context.context_aware + def run_tool_scripts(self, session, return_zip_path=False): + error_context.context("Run Debug tool script to Query original info or value.", LOG_JOB.info) + # Running the PowerShell script on the VM + include_sensitive_data = bool(strtobool(self.params['include_sensitive_data'])) + print(include_sensitive_data) + sensitive_data_flag = "-IncludeSensitiveData" if include_sensitive_data else "" + + # Execute the command on the VM + cmd_run_deg_tool = f"powershell.exe -ExecutionPolicy Bypass -File {self.script_path} {sensitive_data_flag}" + s, o = session.cmd_status_output(cmd_run_deg_tool, timeout=360) + + paths = self._get_path(o, session, sensitive_data=include_sensitive_data) + if include_sensitive_data: + log_folder_path, log_zip_path, dump_folder_path, dump_zip_path = paths + if not all(paths): + test.fail("Debug tool run failed, please check it.") + return paths if return_zip_path else (log_folder_path, dump_folder_path) + else: + log_folder_path, log_zip_path = paths + if not all(paths): + test.fail("Debug tool run failed, please check it.") + return paths if return_zip_path else log_folder_path + + @error_context.context_aware + def windegtool_check_script_execution(self, test, params, env): + if not self.vm: + self.vm = env.get_vm(params["main_vm"]) + self.vm.verify_alive() + + session = self._get_session(params, self.vm) + self._open_session_list.append(session) + session.cmd("cd %s" % self.tmp_dir) + + log_folder_path, log_zip_path = self.run_tool_scripts(session, return_zip_path=True) + if not (log_zip_path and log_folder_path): + test.fail("debug tool run failed, please check it.") + + def run_once(self, test, params, env): + WinDebugToolTest.run_once(self, test, params, env) + + windegtool_check_type = self.params["windegtool_check_type"] + chk_type = "windegtool_check_%s" % windegtool_check_type + if hasattr(self, chk_type): + func = getattr(self, chk_type) + func(test, params, env) + else: + test.error("Could not find matching test, check your config file") + + +def run(test, params, env): + """ + Test CollectSystemInfo.ps1 tool, this case will: + 1) Start VM with virtio-win rpm package. + 2) Execute CollectSystemInfo.ps1 with&without param + '-IncludeSensitiveData'. + 3) Run some basic test for CollectSystemInfo.ps1. + + :param test: kvm test object + :param params: Dictionary with the test parameters + :param env: Dictionary with test environmen. + """ + + collectinfotool_test = WinDebugToolTestBasicCheck(test, params, env) + collectinfotool_test.execute(test, params, env) \ No newline at end of file