Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
win_guest_debugging_tool: Support new feature cases
Browse files Browse the repository at this point in the history
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.

Signed-off-by: Dehan Meng <demeng@redhat.com>
6-dehan committed Dec 30, 2024
1 parent b2108ff commit b707bb3
Showing 2 changed files with 881 additions and 0 deletions.
99 changes: 99 additions & 0 deletions qemu/tests/cfg/win_guest_debugging_tool.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
- 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
- check_zip_package:
windegtool_check_type = zip_package
cmd_extract_zip = 'powershell.exe Expand-Archive -Path "%s" -DestinationPath %s -Force'
cmd_check_folder_size = powershell -c "$folderPath='%s'; $folderSize=(Get-ChildItem -Path $folderPath -Recurse | Measure-Object -Property Length -Sum).Sum; Write-Output $folderSize"
- check_run_tools_multi_times:
windegtool_check_type = run_tools_multi_times
- check_user_friendliness:
windegtool_check_type = user_friendliness
cmd_kill_powershell_process = taskkill /IM powershell.exe /F
cmd_kill_powershell_process1 = powershell.exe -Command "Stop-Process -Name msinfo32 -Force"
invalid_params = "-invalidparam,IncludeSensitiveData,0000,hell,-H,-IncludeSensitiveData -h"
expect_output_prompt = "Usage: .\CollectSystemInfo.ps1 [-IncludeSensitiveData] [-Help]"
script_interrupt_signal_file = 'Collecting_Status.txt'
cmd_dir_del = powershell.exe -Command "Remove-Item -Path '%s' -Recurse -Force -ErrorAction SilentlyContinue"
cmd_query_path = powershell.exe "$lastDir = dir | Select-String 'System*' | Select-Object -Last 1; write-output $lastDir"
- check_disk_registry_collection:
windegtool_check_type = disk_registry_collection
virtio_disk_filepath = "%s\virtio_disk.txt"
new_reg_item = "HKLM:\SYSTEM\CurrentControlSet\Services\viostor\Parameters"
exist_reg_item = "HKLM:\SYSTEM\CurrentControlSet\Services\Disk"
cmd_reg_query = powershell.exe -Command "(Get-ItemProperty -Path %s).%s"
cmd_reg_add_item = powershell.exe "if (-not (Test-Path -Path '%s')) {New-Item -Path %s | Out-Null}"
cmd_reg_add_item_key = powershell.exe "if (-not (Test-Path -Path '%s')) {New-Item -Path %s -Name %s -ItemType Key | Out-Null}"
cmd_reg_set_value = powershell.exe -Command "Set-ItemProperty -Path '%s' -Name '%s' -Value %d"
cmd_reg_del = powershell.exe -Command "Remove-Item -Path '%s' -Recurse -Force -ErrorAction SilentlyContinue"
reg_subkey1 = IoTimeoutValue
reg_subkey2 = TimeoutValue
key_value1 = 100
key_value2 = 150
- check_includeSensitiveData_collection:
windegtool_check_type = includeSensitiveData_collection
include_sensitive_data = True
timeout = 360
reboot_method = system_reset
memory_dmp_file = "%SystemRoot%\Memory.dmp"
mini_dmp_folder = "%SystemRoot%\Minidump"
crash_method = nmi
cmd_check_files = powershell.exe ls %s
- check_trigger_driver_msinfo_collection:
windegtool_check_type = trigger_driver_msinfo_collection
image_snapshot = yes
transfer_timeout = 720
msinfo_file_path = "%s\msinfo32.txt"
drv_list_file_path = "%s\drv_list.csv"
setupapi_dev_file_path = "%s\setupapi.dev.log"
target_driver = pvpanic
cmd_query_oem_inf = powershell.exe -Command "pnputil.exe /enum-drivers | Select-String -Pattern '%s.inf' -Context 1,1 | ForEach-Object { if ($_ -match 'Published Name:\s+(oem\d+\.inf)') { $matches[1] } }"
cmd_install_driver = pnputil.exe /add-driver %s /install
cmd_uninstall_driver = pnputil.exe /delete-driver %s /uninstall /force
cmd_scan_device = pnputil.exe /scan-devices
cmd_backup_driver = Export-WindowsDriver -Online -Destination "C:\DriverBackup"
cmd_check_driver_ver = powershell.exe -Command "Get-WmiObject Win32_PnPSignedDriver | Where-Object DeviceName -eq '%s'"
new_system_name = "NewsystemName"
cmd_change_systemname = powershell.exe -Command "Rename-Computer -NewName %s"
cmd_query_from_file = powershell.exe -Command "Get-Content %s | Select-String -Pattern '%s'"
cmd_check_systemname = echo %computername%
cmd_query_ver_vm = powershell.exe -Command "(Get-CimInstance -ClassName Win32_OperatingSystem).Caption"
cmd_search_2k16_inf_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 } | Where-Object { $_ -match '2k16' }"
- check_networkadapter_collection:
windegtool_check_type = networkadapter_collection
check_adapter_name = powershell.exe -Command "Get-NetAdapter | Select-Object -ExpandProperty Name"
check_adapter_jp_info = powershell.exe -Command "Get-NetAdapterAdvancedProperty -Name '%s' | Where-Object { $_.DisplayName -eq 'Jumbo Packet' } | Select-Object -ExpandProperty DisplayValue"
cmd_set_adapter_jp_info = powershell.exe -Command "Set-NetAdapterAdvancedProperty -Name '%s' -DisplayName 'Jumbo Packet' -DisplayValue %d"
cmd_disable_adapter = powershell.exe -Command "Disable-NetAdapter -Name '%s' -Confirm:$false"
cmd_enable_adapter = powershell.exe -Command "Enable-NetAdapter -Name '%s' -Confirm:$false"
networkfile_path = "%s\NetworkInterfaces.txt"
ipconfigfile_path = "%s\IPConfiguration.txt"
static_dns = 8.8.8.8
cmd_get_dns = powershell.exe -Command (Get-DnsClientServerAddress -AddressFamily IPv4).ServerAddresses
cmd_set_dns = netsh interface ipv4 set dns name="%s" static %s
cmd_set_dns_dhcp = netsh interface ipv4 set dns name="%s" dhcp
- check_documentation:
windegtool_check_type = documentation
standard_docs = "README.md", "LICENSE", "CollectSystemInfo.ps1"
target_doc = "README.md"
query_cmd_from_file = powershell.exe -Command "Get-Content %s | Select-String '```powershell' -Context 0,1"
cmd_cp_file = powershell.exe -Command "cp %s %s"
782 changes: 782 additions & 0 deletions qemu/tests/win_guest_debugging_tool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,782 @@
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", "")
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(
"\\"
)
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()

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)
log_zip_path = f"{log_folder_path}.zip"

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
)
dump_zip_path = f"{dump_folder_path}.zip"
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.")

@error_context.context_aware
def windegtool_check_zip_package(self, test, params, env):
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.")

error_context.context(
"Extract ZIP and check the data files.", LOG_JOB.info
)
session.cmd("cd %s" % self.tmp_dir)
extract_folder = log_zip_path + "_extract"
s, o = session.cmd_status_output(
params["cmd_extract_zip"] % (log_zip_path, extract_folder)
)
if s:
test.error("Extract ZIP failed, please take a look and check.")

error_context.context("Compare the folders", LOG_JOB.info)
extract_folder_size = session.cmd_output(
params["cmd_check_folder_size"] % extract_folder
)
log_folder_size = session.cmd_output(
params["cmd_check_folder_size"] % log_folder_path
)
if log_folder_size != extract_folder_size:
test.fail(
"ZIP package have problem, since the size of it "
"is not same with the original log folder."
)

@error_context.context_aware
def windegtool_check_run_tools_multi_times(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)

error_context.context(
"Run scripts 100 times and check "
"there is no problem", LOG_JOB.info
)
for i in range(1, 5):
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.")
cmd_remove_zip = params["cmd_remove_dir"] % log_zip_path
cmd_remove_folder = params["cmd_remove_dir"] % log_folder_path
cmd_clean_dir = (
"%s && %s" % (cmd_remove_folder, cmd_remove_zip)
)
session.cmd(cmd_clean_dir)

@error_context.context_aware
def windegtool_check_user_friendliness(self, test, params, env):

def _run_script(session):
cmd_run_deg_tool = f"powershell.exe -ExecutionPolicy Bypass -File {self.script_path}"
try:
session.cmd_output(cmd_run_deg_tool, timeout=5)
except ShellTimeoutError:
pass

def _kill_powershell_process(session1):
session1.cmd(params["cmd_kill_powershell_process"])
session1.cmd(params["cmd_kill_powershell_process1"])

if not self.vm:
self.vm = env.get_vm(params["main_vm"])
self.vm.verify_alive()

session = self._get_session(params, self.vm)
session1 = self._get_session(params, self.vm)
self._open_session_list.extend([session, session1])

error_context.context(
"Run script with various of invalid parameters.", LOG_JOB.info
)
session.cmd("cd %s" % self.tmp_dir)
session.cmd("rd /S /Q %s" % self.tmp_dir)
session.cmd_output(
params["cmd_create_dir"] % self.tmp_dir
)
invalid_params = list(params["invalid_params"].split(","))
expect_output_prompt = params["expect_output_prompt"]
for invalid_param in invalid_params:
cmd_run_deg_tool = f"powershell.exe -ExecutionPolicy Bypass -File {self.script_path} {invalid_param}"
o = session.cmd_output(cmd_run_deg_tool, timeout=360)
if expect_output_prompt not in o:
test.fail(
"There should be friendly reminder output %s, telling "
"users how to run the script with reasonable parameters"
"please check it." % expect_output_prompt
)

error_context.context(
"Interrupt script when it's running to check "
"the signal file.", LOG_JOB.info
)
script_thread = threading.Thread(
target=_run_script(session)
)
kill_thread = threading.Thread(
target=_kill_powershell_process(session1)
)
script_thread.start()
time.sleep(5)
kill_thread.start()
script_thread.join()
kill_thread.join()

script_interrupt_signal_file = params["script_interrupt_signal_file"]
log_path = session.cmd_output(params["cmd_query_path"]).split()[0]
session.cmd("cd %s" % log_path)
output = session.cmd_output("dir")
if script_interrupt_signal_file not in output:
test.fail(
f"There should be one {script_interrupt_signal_file} once the script"
f" is interrupted, but there isn't. Please check it."
)

error_context.context(
"Clean invalid files and re-run script again to check "
"whether it could be run well.", LOG_JOB.info
)
session.cmd("cd ../")
session.cmd(params["cmd_dir_del"] % log_path)
self.run_tool_scripts(session)

@error_context.context_aware
def windegtool_check_disk_registry_collection(self, test, params, env):
session = self._get_session(params, self.vm)
self._open_session_list.append(session)
session.cmd("cd %s" % self.tmp_dir)

error_context.context(
"Run script first to collect 'virtio_disk.txt'.", LOG_JOB.info
)
log_folder_path = self.run_tool_scripts(session)
virtio_disk_filepath = params["virtio_disk_filepath"] % log_folder_path
exist_reg_item = params["exist_reg_item"]
reg_subkey1, reg_subkey2 = params["reg_subkey1"], params["reg_subkey2"]
iotimeoutvalue_file = int(session.cmd_output(
params["cmd_findstr_in_file"] % (
virtio_disk_filepath, (exist_reg_item + "\\" + reg_subkey1))
).split(":")[-1].strip())
timeoutvalue_file = int(session.cmd_output(
params["cmd_findstr_in_file"] % (
virtio_disk_filepath, (exist_reg_item + "\\" + reg_subkey2))
).split(":")[-1].strip())
iotimeoutvalue_cmd = int(session.cmd_output(params["cmd_reg_query"] %
(exist_reg_item, reg_subkey1)))
timeoutvalue_cmd = int(session.cmd_output(params["cmd_reg_query"] %
(exist_reg_item, reg_subkey2)))
if (
iotimeoutvalue_cmd != iotimeoutvalue_file
or timeoutvalue_cmd != timeoutvalue_file
):
test.error(
"The value of %s and %s is not same between %s and cmd,"
"please have a check" % (
reg_subkey1, reg_subkey2, virtio_disk_filepath
)
)

error_context.context(
"Edit exist value and create new sub-key for "
"vioscsi/viostor for non-exist value", LOG_JOB.info
)
new_reg_item = params["new_reg_item"]
cmd_reg_add_item = params["cmd_reg_add_item"] % (new_reg_item, new_reg_item)
cmd_reg_add_item_key = params["cmd_reg_add_item_key"]
cmd_reg_set_value = params["cmd_reg_set_value"]
try:
key_value1, key_value2 = int(
params["key_value1"]), int(params["key_value2"])

s, o = session.cmd_status_output(cmd_reg_add_item)
if not s:
session.cmd_output(
cmd_reg_add_item_key % (new_reg_item, new_reg_item, reg_subkey1)
)
session.cmd_output(
cmd_reg_add_item_key % (new_reg_item, new_reg_item, reg_subkey2)
)
else:
test.error(
"Add register item for vioscsi/viostor failed, please help check."
)

session.cmd_output(cmd_reg_set_value % (exist_reg_item, reg_subkey1, key_value1))
session.cmd_output(cmd_reg_set_value % (new_reg_item, reg_subkey1, key_value1))
session.cmd_output(cmd_reg_set_value % (new_reg_item, reg_subkey2, key_value2))

error_context.context("Re-run guest debug tool script", LOG_JOB.info)
new_log_folder_path = self.run_tool_scripts(session)
new_virtio_disk_filepath = params["virtio_disk_filepath"] % new_log_folder_path
exist_iotimeoutvalue_file = int(session.cmd_output(
params["cmd_findstr_in_file"] % (
new_virtio_disk_filepath, (exist_reg_item + "\\" + reg_subkey1))
).split(":")[-1].strip())
new_iotimeoutvalue_file = int(session.cmd_output(params["cmd_findstr_in_file"] %
(new_virtio_disk_filepath,
(new_reg_item + "\\" + reg_subkey1))).split(":")[-1].strip())
new_timeoutvalue_file = int(session.cmd_output(params["cmd_findstr_in_file"] %
(new_virtio_disk_filepath,
(new_reg_item + "\\" + reg_subkey2))).split(":")[-1].strip())

exist_iotimeoutvalue_cmd = int(session.cmd_output(params["cmd_reg_query"] % (exist_reg_item, reg_subkey1)))
new_iotimeoutvalue_cmd = int(session.cmd_output(params["cmd_reg_query"] % (new_reg_item, reg_subkey1)))
new_timeoutvalue_cmd = int(session.cmd_output(params["cmd_reg_query"] % (new_reg_item, reg_subkey2)))
print(exist_iotimeoutvalue_file, new_iotimeoutvalue_file, new_timeoutvalue_file, exist_iotimeoutvalue_cmd,
new_iotimeoutvalue_cmd, new_timeoutvalue_cmd)
if (exist_iotimeoutvalue_cmd != exist_iotimeoutvalue_file or
new_iotimeoutvalue_cmd != new_iotimeoutvalue_file or
new_timeoutvalue_cmd != new_timeoutvalue_file):
test.error(
"The value of %s and %s is not same between %s and cmd, please have a check" % (
reg_subkey1, reg_subkey2, new_log_folder_path
)
)
finally:
session.cmd_output(params["cmd_reg_del"] % new_reg_item)
session.cmd_output(
cmd_reg_set_value % (exist_reg_item, reg_subkey1, iotimeoutvalue_cmd)
)

@error_context.context_aware
def windegtool_check_includeSensitiveData_collection(self, test, params, env):

session = self._get_session(params, self.vm)
self._open_session_list.append(session)

error_context.context("Trigger BSOD situation.", LOG_JOB.info)
crash_method = params["crash_method"]
if crash_method == "nmi":
timeout = int(params.get("timeout", 360))
self.vm.monitor.nmi()
time.sleep(timeout)
self.vm.reboot(
session, method=params["reboot_method"], timeout=timeout
)

session = self._get_session(params, self.vm)
self._open_session_list.append(session)
session.cmd("cd %s" % self.tmp_dir)

error_context.context("Check the dmp files are existed.", LOG_JOB.info)
cmd_check_dmp_files = params["cmd_check_files"] % params["memory_dmp_file"]
cmd_check_minidmp_files = params["cmd_check_files"] % params["mini_dmp_folder"]
output = session.cmd_output(
"%s && %s" % (cmd_check_dmp_files, cmd_check_minidmp_files)
)
if "dmp" not in output:
test.error("Dump file should be existed, please have a check")
else:
self.run_tool_scripts(session)

@error_context.context_aware
def windegtool_check_trigger_driver_msinfo_collection(self, test, params, env):
session = self._get_session(params, self.vm)
self._open_session_list.append(session)

error_context.context(
"Run script firstly to check system name and driver info.", LOG_JOB.info
)
session.cmd("cd %s" % self.tmp_dir)
log_path = self.run_tool_scripts(session)
msinfo_file_path = params["msinfo_file_path"] % log_path
drv_list_file_path = params["drv_list_file_path"] % log_path
target_driver = params["target_driver"]

old_systemname = str(session.cmd_output(params["cmd_query_from_file"] %
(msinfo_file_path, "System Name:")).split(":")[1]).strip()
systemname_guest = str(session.cmd_output(params["cmd_check_systemname"])).strip()
if old_systemname != systemname_guest:
test.error(
"The system name are different between cmd and file that"
" collect by tool, Please have a check"
)
drvinfo_output = session.cmd_output(
params["cmd_query_from_file"] % (drv_list_file_path, target_driver)
)
if target_driver not in drvinfo_output:
test.error(
"%s doesn't installed, there is no info about it, "
"Please have a check and change another target driver to test"
)

error_context.context(
"Change the system name and uninstall certain driver.", LOG_JOB.info
)
new_system_name = params["new_system_name"]
session.cmd(params["cmd_change_systemname"] % new_system_name)
win_ver = str(session.cmd_output(
params["cmd_query_ver_vm"], timeout=60)
).strip()
if "2016" not in win_ver:
driver_oem_file = session.cmd_output(
params["cmd_query_oem_inf"] % target_driver
).strip()
cmd_uninstall_driver = params["cmd_uninstall_driver"] % driver_oem_file
s, o = session.cmd_status_output(cmd_uninstall_driver)
else:
cmd_search_2k16_inf = (
params["cmd_search_2k16_inf_file_global"] % (target_driver + ".inf")
)
w2k16_inf = str(session.cmd_output(
cmd_search_2k16_inf, timeout=60)
).strip()
cmd_install_driver = params["cmd_install_driver"] % w2k16_inf
s, o = session.cmd_status_output(cmd_install_driver)
if s or "Fail" in o:
test.error(
"Fail to execute %s driver, please take a look." % target_driver
)

error_context.context(
"Re-Run script after rebooting to check whether system"
" name and driver info changed.",LOG_JOB.info
)
session.cmd_output(params["reboot_command"])
session = self._get_session(params, self.vm)
self._open_session_list.append(session)

session.cmd("cd %s" % self.tmp_dir)
new_log_path = self.run_tool_scripts(session)
new_msinfo_file_path = params["msinfo_file_path"] % new_log_path
new_drv_list_file_path = params["drv_list_file_path"] % new_log_path
new_setupapi_dev_file_path = params["setupapi_dev_file_path"] % new_log_path
new_systemname = session.cmd_output(
params["cmd_query_from_file"] % (new_msinfo_file_path, "System Name:")
).split(":")[1].strip()
if new_system_name.upper() not in str(new_systemname):
test.fail(
"New systemname wasn't captured by tool, Please have a check"
)
new_drvinfo_output = session.cmd_output(
params["cmd_query_from_file"] % (new_drv_list_file_path, target_driver)
)
if target_driver in new_drvinfo_output:
test.fail(
"Driver should be uninstalled, but tool wasn't captured this situation, Please have a check"
)
if "2016" not in win_ver:
regex_command = cmd_uninstall_driver.replace(" ", r"\s+").replace(".", r"\.")
setupapi_output = session.cmd_output(
params["cmd_query_from_file"] % (new_setupapi_dev_file_path, regex_command)
)
if "/delete-driver" not in setupapi_output:
test.fail(
"Driver execution operation was not captured, Please have a check."
)
else:
setupapi_output = session.cmd_output(
params["cmd_query_from_file"] % (new_setupapi_dev_file_path, "pnputil.exe")
)
if "/add-driver" not in setupapi_output:
test.fail(
"Driver execution operation was not captured, Please have a check."
)

@error_context.context_aware
def windegtool_check_networkadapter_collection(self, test, params, env):

session = self._get_session(params, self.vm)
self._open_session_list.append(session)
session.cmd("cd %s" % self.tmp_dir)

error_context.context(
"Run tool script firstly, and conducting "
"raw data comparison tests", LOG_JOB.info
)
adapter_name = session.cmd_output(params["check_adapter_name"]).strip()
original_log_path = self.run_tool_scripts(session)

original_networkfile_path = params["networkfile_path"] % original_log_path
raw_jp_value_from_file = session.cmd_output(params["cmd_findstr_in_file"] %
(original_networkfile_path, "Jumbo Packet"))
original_jp_value_from_file = int(raw_jp_value_from_file.split()[5])
original_jp_value_from_cmd = int(session.cmd_output(
params["check_adapter_jp_info"] % adapter_name)
)
if original_jp_value_from_cmd != original_jp_value_from_file:
test.error(
"Network info collection seems have problem, the value of"
"Jumbo Packet is not same between file and cmd."
)

ipconfigfile_path = params["ipconfigfile_path"] % original_log_path
original_ipconfig_output = session.cmd_output(params["cmd_findstr_in_file"] %
(ipconfigfile_path, adapter_name))
dns_info = session.cmd_output(params["cmd_get_dns"]).split()
for dns_info_item in dns_info:
print("Yes DNS existed") if dns_info_item in original_ipconfig_output else print("No, DNS doesn't existed")

error_context.context(
"Change the dhcp and check whether the file changed", LOG_JOB.info
)
static_dns = params["static_dns"]
session.cmd_output(params["cmd_set_dns"] % (adapter_name, static_dns), timeout=360)

log_folder_path_new = self.run_tool_scripts(session)
ipconfigfile_path = params["ipconfigfile_path"] % log_folder_path_new
new_ipconfig_output = session.cmd_output(
params["cmd_findstr_in_file"] % (ipconfigfile_path, static_dns)
)
if static_dns not in new_ipconfig_output:
test.fail(
"DNS should be changed but it's not, please check it."
)
else:
error_context.context(
"Checkpoint is pass, Re-enable adapter for next checkpoint.", LOG_JOB.info
)
session.cmd(params["cmd_set_dns_dhcp"] % adapter_name)

error_context.context(
"Changed the 'Jumbo Packet' value and compare.", LOG_JOB.info
)
try:
session.cmd_output(
params["cmd_set_adapter_jp_info"] % (adapter_name, 9014), timeout=360
)
except ShellTimeoutError:
session = self._get_session(params, self.vm)
self._open_session_list.append(session)
session.cmd("cd %s" % self.tmp_dir)

log_folder_path_new = self.run_tool_scripts(session)
networkfile_path = params["networkfile_path"] % log_folder_path_new
raw_jp_value = session.cmd_output(
params["cmd_findstr_in_file"] % (networkfile_path, "Jumbo Packet")
)
new_jp_value = int(raw_jp_value.split()[5])
print("new_jp_value: %s" % new_jp_value)
if original_jp_value_from_file == new_jp_value:
test.fail(
"Jumbo Packet should not be same with the original one, please check it."
)
if new_jp_value != 9014:
test.error(
"Jumbo Packet should be the new value, but it's not somehow, Please check it."
)

error_context.context("Recover the env.", LOG_JOB.info)
try:
session.cmd(
params["cmd_set_adapter_jp_info"] % (
adapter_name, original_jp_value_from_file
)
)
except ShellTimeoutError:
session = self._get_session(params, self.vm)
self._open_session_list.append(session)
session.cmd("cd %s" % self.tmp_dir)
change_back_jp_value = int(session.cmd_output(params["check_adapter_jp_info"] % adapter_name))
if change_back_jp_value != original_jp_value_from_file:
test.error("Please have a check, the value wasn't changed back to original.")

@error_context.context_aware
def windegtool_check_documentation(self, test, params, env):
def _clean_output(output):
lines = output.splitlines()
cleaned_lines = []

for line in lines:
line = line.strip()
if not line or "powershell" in line:
continue
cleaned_lines.append(line)
return "\n".join(cleaned_lines)

session = self._get_session(params, self.vm)
self._open_session_list.append(session)

error_context.context(
"Check all relevant official documents to "
"ensure they are complete", LOG_JOB.info
)
output = str(
session.cmd_output("dir %s\\" % self.script_dir)
).strip()
standard_docs = (params["standard_docs"]).split(",")
for standard_doc in standard_docs:
if standard_doc not in output:
test.error(f"There is no file {standard_doc}, please contact with vendor.")

error_context.context(
"Address usable commands and execute them to ensure "
"they are executable and accurate", LOG_JOB.info
)
target_doc_path = "%s\\%s" % (self.script_dir, params["target_doc"])
target_output = str(
session.cmd_output(params["query_cmd_from_file"] % target_doc_path)
).strip()
executable_cmds = _clean_output(target_output).splitlines()
executable_cmd_final = 'powershell.exe -Command "'
for executable_cmd in executable_cmds:
executable_cmd_final += executable_cmd + "; "
executable_cmd_final = executable_cmd_final.rstrip("; ") + '"'
session.cmd(params["cmd_cp_file"] % (self.script_path, self.tmp_dir))
session.cmd("cd %s" % self.tmp_dir)
s, o = session.cmd_status_output(executable_cmd_final, timeout=360)

include_sensitive_data = True if "-IncludeSensitiveData" in executable_cmd_final else False
paths = self._get_path(
o, session, sensitive_data=include_sensitive_data
)
if not all(paths):
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)

0 comments on commit b707bb3

Please sign in to comment.