-
Notifications
You must be signed in to change notification settings - Fork 173
Commit
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 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 <[email protected]>
- Loading branch information
Showing
2 changed files
with
274 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |