summaryrefslogtreecommitdiffstats
path: root/src/spdk/test/vhost/windows
diff options
context:
space:
mode:
Diffstat (limited to 'src/spdk/test/vhost/windows')
-rwxr-xr-xsrc/spdk/test/vhost/windows/windows.sh141
-rw-r--r--src/spdk/test/vhost/windows/windows_fs_test.ps178
-rw-r--r--src/spdk/test/vhost/windows/windows_scsi_compliance.ps173
-rwxr-xr-xsrc/spdk/test/vhost/windows/windows_scsi_compliance.py147
-rwxr-xr-xsrc/spdk/test/vhost/windows/windows_scsi_compliance.sh89
5 files changed, 528 insertions, 0 deletions
diff --git a/src/spdk/test/vhost/windows/windows.sh b/src/spdk/test/vhost/windows/windows.sh
new file mode 100755
index 000000000..6bf8573f7
--- /dev/null
+++ b/src/spdk/test/vhost/windows/windows.sh
@@ -0,0 +1,141 @@
+#!/usr/bin/env bash
+
+testdir=$(readlink -f $(dirname $0))
+rootdir=$(readlink -f $testdir/../../..)
+source $rootdir/test/common/autotest_common.sh
+source $rootdir/test/vhost/common.sh
+
+rpc_py="$rootdir/scripts/rpc.py -s $(get_vhost_dir 0)/rpc.sock"
+ctrl_type="spdk_vhost_scsi"
+ssh_pass=""
+vm_num="0"
+vm_image="/home/sys_sgsw/windows_server.qcow2"
+
+function usage() {
+ [[ -n $2 ]] && (
+ echo "$2"
+ echo ""
+ )
+ echo "Windows Server automated test"
+ echo "Usage: $(basename $1) [OPTIONS]"
+ echo "--vm-ssh-pass=PASSWORD Text password for the VM"
+ echo "--vm-image=PATH Path to qcow2 image of Windows VM"
+ echo "--ctrl-type=TYPE Controller type to use for test:"
+ echo " spdk_vhost_scsi - use spdk vhost scsi"
+ echo " spdk_vhost_blk - use spdk vhost block"
+ echo "-x set -x for script debug"
+ echo "-h, --help Print help and exit"
+
+ exit 0
+}
+
+while getopts 'xh-:' optchar; do
+ case "$optchar" in
+ -)
+ case "$OPTARG" in
+ help) usage $0 ;;
+ vm-ssh-pass=*) ssh_pass="${OPTARG#*=}" ;;
+ vm-image=*) vm_image="${OPTARG#*=}" ;;
+ ctrl-type=*) ctrl_type="${OPTARG#*=}" ;;
+ esac
+ ;;
+ h) usage $0 ;;
+ x)
+ set -x
+ x="-x"
+ ;;
+ *) usage $0 "Invalid argument '$OPTARG'" ;;
+ esac
+done
+
+# For some reason there is a problem between using SSH key authentication
+# and Windows UAC. Some of the powershell commands fail due to lack of
+# permissons, despite script running in elevated mode.
+# There are some clues about this setup that suggest this might not work properly:
+# https://superuser.com/questions/181581/how-can-i-run-something-as-administrator-via-cygwins-ssh
+# https://cygwin.com/ml/cygwin/2004-09/msg00087.html
+# But they apply to rather old Windows distributions.
+# Potentially using Windows Server 2016 and newer may solve the issue
+# due to OpenSSH being available directly from Windows Store.
+function vm_sshpass() {
+ vm_num_is_valid $1 || return 1
+
+ local ssh_cmd
+ ssh_cmd="sshpass -p $2 ssh \
+ -o UserKnownHostsFile=/dev/null \
+ -o StrictHostKeyChecking=no \
+ -o User=root \
+ -p $(vm_ssh_socket $1) $VM_SSH_OPTIONS 127.0.0.1"
+
+ shift 2
+ $ssh_cmd "$@"
+}
+
+if [[ -z "$ssh_pass" ]]; then
+ error "Please specify --vm-ssh-pass parameter"
+fi
+
+trap 'error_exit "${FUNCNAME}" "${LINENO}"; rm -f $aio_file' SIGTERM SIGABRT ERR
+
+vm_kill_all
+
+# Run vhost without debug!
+# Windows Virtio drivers use indirect descriptors without negotiating
+# their feature flag, which is explicitly forbidden by the Virtio 1.0 spec.
+# "(2.4.5.3.1 Driver Requirements: Indirect Descriptors)
+# The driver MUST NOT set the VIRTQ_DESC_F_INDIRECT flag unless the
+# VIRTIO_F_INDIRECT_DESC feature was negotiated.".
+# Violating this rule doesn't cause any issues for SPDK vhost,
+# but triggers an assert, so we can only run Windows VMs with non-debug SPDK builds.
+notice "running SPDK vhost"
+vhost_run 0
+notice "..."
+
+# Prepare bdevs for later vhost controllers use
+# Nvme bdev is automatically constructed during vhost_run
+# by using scripts/gen_nvme.sh. No need to add it manually.
+# Using various sizes to better identify bdevs if no name in BLK
+# is available
+# TODO: use a param for blocksize for AIO and Malloc bdevs
+aio_file="$SPDK_TEST_STORAGE/aio_disk"
+dd if=/dev/zero of=$aio_file bs=1M count=512
+$rpc_py bdev_aio_create $aio_file Aio0 512
+$rpc_py bdev_malloc_create -b Malloc0 256 512
+$rpc_py bdev_get_bdevs
+
+# Create vhost controllers
+# Prepare VM setup command
+setup_cmd="vm_setup --force=0 --memory=8192"
+setup_cmd+=" --os=$vm_image"
+
+if [[ "$ctrl_type" == "spdk_vhost_scsi" ]]; then
+ $rpc_py vhost_create_scsi_controller naa.0.0
+ $rpc_py vhost_scsi_controller_add_target naa.0.0 0 Nvme0n1
+ $rpc_py vhost_scsi_controller_add_target naa.0.0 1 Malloc0
+ $rpc_py vhost_scsi_controller_add_target naa.0.0 2 Aio0
+ setup_cmd+=" --disk-type=spdk_vhost_scsi --disks=0"
+elif [[ "$ctrl_type" == "spdk_vhost_blk" ]]; then
+ $rpc_py vhost_create_blk_controller naa.0.0 Nvme0n1
+ $rpc_py vhost_create_blk_controller naa.1.0 Malloc0
+ $rpc_py vhost_create_blk_controller naa.2.0 Aio0
+ setup_cmd+=" --disk-type=spdk_vhost_blk --disks=0:1:2"
+fi
+$rpc_py vhost_get_controllers
+$setup_cmd
+
+# Spin up VM
+vm_run "$vm_num"
+vm_wait_for_boot "300" "$vm_num"
+
+vm_sshpass "$vm_num" "$ssh_pass" "mkdir /cygdrive/c/fs_test"
+vm_scp "$vm_num" "$testdir/windows_fs_test.ps1" "127.0.0.1:/cygdrive/c/fs_test"
+vm_sshpass "$vm_num" "$ssh_pass" "cd /cygdrive/c/fs_test; powershell.exe -file windows_fs_test.ps1"
+
+notice "Shutting down Windows VM..."
+# Killing, actually. #TODO: implement vm_windwows_shutdown() function
+vm_kill $vm_num
+
+notice "Shutting down SPDK vhost app..."
+vhost_kill 0
+
+rm -f $aio_file
diff --git a/src/spdk/test/vhost/windows/windows_fs_test.ps1 b/src/spdk/test/vhost/windows/windows_fs_test.ps1
new file mode 100644
index 000000000..cda1b53f2
--- /dev/null
+++ b/src/spdk/test/vhost/windows/windows_fs_test.ps1
@@ -0,0 +1,78 @@
+# Get the ID and security principal of the current user account
+$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
+$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
+
+# Get the security principal for the Administrator role
+$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
+
+# Check to see if we are currently running "as Administrator"
+if ($myWindowsPrincipal.IsInRole($adminRole)) {
+ # We are running "as Administrator" - so change the title and background color to indicate this
+ $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)"
+ $Host.UI.RawUI.BackgroundColor = "DarkBlue"
+ clear-host
+} else
+ {
+ # We are not running "as Administrator" - so relaunch as administrator
+
+ # Create a new process object that starts PowerShell
+ $newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell";
+
+ # Specify the current script path and name as a parameter
+ $newProcess.Arguments = $myInvocation.MyCommand.Definition;
+
+ # Indicate that the process should be elevated
+ $newProcess.Verb = "runas";
+
+ # Start the new process
+ [System.Diagnostics.Process]::Start($newProcess);
+
+ # Exit from the current, unelevated, process
+ exit
+}
+
+# Set bash -e equivalent
+$ErrorActionPreference = "Stop"
+
+$filesystems=@("NTFS", "FAT32", "FAT")
+$disks = get-disk | Where-Object FriendlyName -NotMatch "QEMU"
+Start-Sleep 2
+foreach($disk in $disks)
+{
+ $size = $disk.Size
+ $number = $disk.Number
+ $serial = $disk.SerialNumber
+ $model = $disk.model.Trim()
+ $size = $size -replace " ", "_"
+ $model = $model -replace " ", "_"
+
+ $label = "${number}_${model}_${serial}_${size}"
+ echo "Running tests for disk $label"
+ start-sleep 2
+
+ Try {
+ Initialize-Disk -Number $disk.Number -PartitionStyle MBR
+ } Catch {
+ Clear-Disk -Number $disk.Number -RemoveData -Confirm:$false
+ Initialize-Disk -Number $disk.Number -PartitionStyle MBR
+ }
+ echo "`tDisk initialized"
+ start-sleep 2
+
+ $part = New-Partition -DiskNumber $disk.Number -UseMaximumSize -AssignDriveLetter
+ echo "`tCreated partition $($part.DriveLetter)"
+ start-sleep 2
+
+ foreach($fs in $filesystems) {
+ echo "`tTrying to format $($part.DriveLetter) with $fs"
+ Try {
+ $vol = Format-Volume -DriveLetter $part.DriveLetter -FileSystem $fs -Confirm:$false
+ } Catch [Exception] {
+ echo $_.Exception.GetType().FullName, $_.Exception.Message
+ echo $_.Exception | format-list -force
+ exit 1
+ }
+ echo "`tPartition $($part.DriveLetter) formatted with $fs filesystem"
+ start-sleep 2
+ }
+}
diff --git a/src/spdk/test/vhost/windows/windows_scsi_compliance.ps1 b/src/spdk/test/vhost/windows/windows_scsi_compliance.ps1
new file mode 100644
index 000000000..80d86e805
--- /dev/null
+++ b/src/spdk/test/vhost/windows/windows_scsi_compliance.ps1
@@ -0,0 +1,73 @@
+# Get the ID and security principal of the current user account
+$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
+$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
+
+# Get the security principal for the Administrator role
+$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
+
+# Check to see if we are currently running "as Administrator"
+if ($myWindowsPrincipal.IsInRole($adminRole))
+ {
+ # We are running "as Administrator" - so change the title and background color to indicate this
+ $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)"
+ $Host.UI.RawUI.BackgroundColor = "DarkBlue"
+ clear-host
+ }
+else
+ {
+ # We are not running "as Administrator" - so relaunch as administrator
+
+ # Create a new process object that starts PowerShell
+ $newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell";
+
+ # Specify the current script path and name as a parameter
+ $newProcess.Arguments = $myInvocation.MyCommand.Definition;
+
+ # Indicate that the process should be elevated
+ $newProcess.Verb = "runas";
+
+ # Start the new process
+ [System.Diagnostics.Process]::Start($newProcess);
+
+ # Exit from the current, unelevated, process
+ exit
+ }
+# Run your code that needs to be elevated here
+get-disk | Where-Object FriendlyName -NotMatch "QEMU" | Initialize-Disk -PartitionStyle MBR
+Start-Sleep 2
+get-disk | Where-Object FriendlyName -NotMatch "QEMU" | Clear-Disk -RemoveData -Confirm:$false
+Start-Sleep 2
+get-disk | Where-Object FriendlyName -NotMatch "QEMU" | Initialize-Disk -PartitionStyle MBR
+Start-Sleep 2
+
+$disks = get-disk | Where-Object FriendlyName -NotMatch "QEMU"
+Start-Sleep 2
+foreach($disk in $disks)
+{
+
+ $phy_bs = $disk.PhysicalSectorSize
+ $model = $disk.model
+ $serial = $disk.SerialNumber
+
+ $label = ""
+ $label += $model.Trim() + "_" + $serial + "_" + $phy_bs
+ $label = $label -replace " ", "_"
+ echo $label
+ start-sleep 2
+
+ $part = New-Partition -DiskNumber $disk.Number -UseMaximumSize -AssignDriveLetter
+ echo $part.DriveLetter
+ start-sleep 2
+
+ $vol = Format-Volume -DriveLetter $part.DriveLetter -FileSystem NTFS -Confirm:$false
+ echo $vol
+ start-sleep 2
+
+ cd C:\SCSI
+ .\scsicompliancetest.exe \\.\$($vol.DriveLetter): -full | tee "C:\SCSI\WIN_SCSI_1_$label.log"
+ start-sleep 2
+ mv .\scsicompliance.log.wtl ".\WIN_SCSI_1_$label.wtl"
+ .\scsicompliance.exe /Device \\.\$($vol.DriveLetter): /Operation Test /Scenario Common | tee "C:\SCSI\WIN_SCSI_2_$label.log"
+ start-sleep 2
+ mv .\scsicompliance.wtl ".\WIN_SCSI_2_$label.wtl"
+}
diff --git a/src/spdk/test/vhost/windows/windows_scsi_compliance.py b/src/spdk/test/vhost/windows/windows_scsi_compliance.py
new file mode 100755
index 000000000..a0f4ea63c
--- /dev/null
+++ b/src/spdk/test/vhost/windows/windows_scsi_compliance.py
@@ -0,0 +1,147 @@
+#!/usr/bin/env python3
+import os
+import sys
+import re
+import pprint
+import collections
+
+os.chdir(os.path.join(os.path.dirname(sys.argv[0]), "results"))
+
+scsi_logs = filter(lambda x: x.endswith(".log"), os.listdir("./"))
+scsi_1_pattern = re.compile(r"(ASSERTION\s[1-9][\d+]?\.\d+\s)(.+\s)([\w\W]+?)(Result:\s)(\w+)", re.I | re.M)
+scsi_2_pattern = re.compile(r"(?:Start:\s)(ASSERTION:\s)?(.+)(?:,.+=\s)([\w\W]+?)(End:\s)(\w+)(,.*)", re.I | re.M)
+fails = []
+warns = []
+
+expected_warns = [
+ "MODE_SELECT_6_MODE_SENSE_6_Checking_Parameters_Savable_PS_bit",
+ "MODE_SELECT_10_MODE_SENSE_10_Checking_Parameters_Savable_PS_bit",
+ "MODE_SELECT_10_Changing_WCE",
+ "MODE_SELECT_10_MODE_SENSE_10_Checking_that_WCE_has_been_cleared",
+ "MODE_SELECT_10_MODE_SENSE_10_Checking_that_Saved_Values_have_changed",
+ "MODE_SELECT_10_setting_WCE",
+ "MODE_SELECT_10_MODE_SENSE_10_Checking_that_WCE_has_been_set",
+ "MODE_SELECT_10_Attempting_to_restore_original_values",
+ "MODE_SELECT_10_MODE_SENSE_10_Verifying_values_were_restored",
+ "ASSERTION_VERIFY_16_Support_Test",
+]
+
+expected_fails = [
+ "ASSERTION_READ_6_Read-With-Disk-Cache-Cleared_Test",
+ "ASSERTION_READ_10_Read-With-Disk-Cache-Cleared_Test",
+ "ASSERTION_READ_16_Read-With-Disk-Cache-Cleared_Test",
+ "ASSERTION_INQUIRY_Checking_Identification_Descriptors_in_VPD_page_0x83",
+ "ASSERTION_VERIFY_10_Support_Test",
+]
+
+results = {"1": collections.OrderedDict(),
+ "2": collections.OrderedDict()}
+
+for log in scsi_logs:
+ # Choose regex pattern depending on tests version
+ pattern = scsi_1_pattern if "WIN_SCSI_1" in log else scsi_2_pattern
+
+ # Read log file contents
+ try:
+ with open(log, 'r') as fh:
+ fh = open(log, 'r')
+ log_text = fh.read()
+ # Dir name for saving split result files of currently processed log file
+ d_name = log.split(".")[0]
+ try:
+ os.mkdir(d_name)
+ except OSError:
+ pass
+ except IOError as e:
+ print("ERROR: While opening log file: {log_file}".format(log_file=log))
+ exit(1)
+
+ # Parse log file contents
+ matches_found = re.findall(pattern, log_text)
+ if len(matches_found) < 1:
+ print("ERROR: No results found in file {log_file}!".format(log_file=log))
+ exit(1)
+
+ # Go through output for each test from log file; parse and save to dict
+ for m in matches_found:
+ test_name = re.sub(r"\s+", "_", (m[0] + m[1]).strip())
+ test_name = re.sub(r"[():]", "", test_name)
+ test_name = test_name[0:-1] if "." in test_name[-1] else test_name
+ tc_result = m[4].upper()
+
+ if "FAIL" in tc_result.upper():
+ fails.append([log, test_name, tc_result])
+ elif "WARN" in tc_result.upper():
+ warns.append([log, test_name, tc_result])
+
+ # Save output to separate file
+ with open(os.path.join("./", d_name, test_name), 'w') as fh:
+ for line in m:
+ fh.write(line)
+
+ # Also save in dictionary for later use in generating HTML results summary
+ ver = "1" if "WIN_SCSI_1" in log else "2"
+ try:
+ results[ver][test_name][d_name] = tc_result
+ except KeyError:
+ results[ver][test_name] = collections.OrderedDict()
+ results[ver][test_name][d_name] = tc_result
+
+
+# Generate HTML file with results table
+with open(os.path.join("./", "results.html"), 'a') as fh:
+ html = "<html>"
+ for suite_ver in results.keys():
+ html += """"<h2> WIN_SCSI_{ver} </h2>
+ <table bgcolor=\"#ffffff\" border=\"1px solid black;>\"""".format(ver=suite_ver)
+
+ # Print header
+ html += "<tr><th>Test name</th>"
+ disks_header = set()
+
+ for _ in results[suite_ver].keys():
+ for disk in results[suite_ver][_].keys():
+ disks_header.add(disk)
+
+ for disk in disks_header:
+ html += "<th>{disk}</th>".format(disk=disk)
+ html += "</tr>"
+
+ # Print results
+ for test in results[suite_ver].keys():
+ html += "<tr><td>{f_name}</td>".format(f_name=test)
+ for disk in disks_header:
+ try:
+ result = results[suite_ver][test][disk]
+
+ html += "<td"
+ if "PASS" in result:
+ html += " bgcolor=\"#99ff33\">"
+ else:
+ html += " bgcolor=\"#ff5050\">"
+
+ html += "<a href={file}>{result}</a>".format(result=result, file=os.path.join("./", disk, test))
+ html += "</td>"
+
+ except KeyError:
+ html += "<td bgcolor=\"#ffff99\"></br></td>"
+ html += "</tr>"
+ html += "</table></br>"
+ html += "</html>"
+ fh.write(html)
+
+if warns:
+ not_expected_warns = [w for w in warns if w[1] not in expected_warns and "WIN_SCSI_2" in w[0]]
+ print("INFO: Windows SCSI compliance warnings:")
+ pprint.pprint(warns, width=150)
+
+if fails:
+ not_expected_fails = [f for f in fails if f[1] not in expected_fails and "WIN_SCSI_2" in f[0]]
+ print("INFO: Windows SCSI compliance fails:")
+ pprint.pprint(fails, width=150)
+
+if not_expected_warns or not_expected_fails:
+ print("Not expected fails / warnings:")
+ pprint.pprint(not_expected_warns, width=150)
+ pprint.pprint(not_expected_fails, width=150)
+ exit(1)
diff --git a/src/spdk/test/vhost/windows/windows_scsi_compliance.sh b/src/spdk/test/vhost/windows/windows_scsi_compliance.sh
new file mode 100755
index 000000000..d7c854592
--- /dev/null
+++ b/src/spdk/test/vhost/windows/windows_scsi_compliance.sh
@@ -0,0 +1,89 @@
+#!/usr/bin/env bash
+
+testdir=$(readlink -f $(dirname $0))
+rootdir=$(readlink -f $testdir/../../..)
+source $rootdir/test/common/autotest_common.sh
+source $rootdir/test/vhost/common.sh
+
+# Tested with windows vm with OS Name: Microsoft Windows Server 2012 R2 Datacenter
+# and OS Version: 6.3.9600 N/A Build 9600
+# In order to run this test with windows vm
+# windows virtio scsi driver must be installed
+WINDOWS_IMG="/home/sys_sgsw/windows_scsi_compliance/windows_vm_image.qcow2"
+aio_file="$SPDK_TEST_STORAGE/aio_disk"
+ssh_pass=""
+vm_num=1
+keep_results_dir=false
+rpc_py="$rootdir/scripts/rpc.py -s $(get_vhost_dir 0)/rpc.sock"
+
+function usage() {
+ [[ -n $2 ]] && (
+ echo "$2"
+ echo ""
+ )
+ echo "Windows Server scsi compliance test"
+ echo "Usage: $(basename $1) [OPTIONS]"
+ echo " --vm-ssh-pass=PASSWORD Text password for the VM"
+ echo " --vm-image-path Path of windows image"
+ echo " --keep_results Do not delete dir with results"
+
+ exit 0
+}
+
+while getopts 'h-:' optchar; do
+ case "$optchar" in
+ -)
+ case "$OPTARG" in
+ help) usage $0 ;;
+ vm-ssh-pass=*) ssh_pass="${OPTARG#*=}" ;;
+ vm-image-path=*) WINDOWS_IMG="${OPTARG#*=}" ;;
+ keep_results*) keep_results_dir=true ;;
+ esac
+ ;;
+ h) usage $0 ;;
+ *) usage $0 "Invalid argument '$OPTARG'" ;;
+ esac
+done
+
+trap 'rm -f $aio_file; rm -rf $testdir/results; error_exit' SIGINT SIGTERM ERR
+
+VM_PASSWORD="$ssh_pass"
+mkdir -p $testdir/results
+dd if=/dev/zero of=$aio_file bs=1M count=512
+
+timing_enter vhost_run
+vhost_run 0
+$rpc_py bdev_nvme_set_hotplug -e
+$rpc_py bdev_malloc_create 256 4096 -b Malloc0
+$rpc_py bdev_aio_create $aio_file Aio0 512
+$rpc_py bdev_get_bdevs
+$rpc_py vhost_create_scsi_controller naa.vhost.1
+$rpc_py vhost_scsi_controller_add_target naa.vhost.1 0 Nvme0n1
+$rpc_py vhost_scsi_controller_add_target naa.vhost.1 1 Malloc0
+# TODO: Currently there is bug for aio device. Disable this test
+# $rpc_py vhost_scsi_controller_add_target naa.vhost.1 2 Aio0
+timing_exit vhost_run
+
+timing_enter start_vm
+vm_setup --force=1 --disk-type=spdk_vhost_scsi --os=$WINDOWS_IMG --disks=vhost --memory=4096
+vm_run "1"
+# Wait until VM goes up
+vm_wait_for_boot "300" "$vm_num"
+timing_exit start_vm
+
+vm_scp "$vm_num" $testdir/windows_scsi_compliance.ps1 127.0.0.1:/cygdrive/c/SCSI/
+vm_sshpass "$vm_num" "$ssh_pass" "cd /cygdrive/c/SCSI; powershell.exe -file windows_scsi_compliance.ps1"
+vm_scp "$vm_num" 127.0.0.1:/cygdrive/c/SCSI/WIN_SCSI_* $testdir/results/
+dos2unix $testdir/results/WIN_SCSI_*.log
+
+notice "Kill vm 1"
+vm_kill "$vm_num"
+notice "Kill spdk"
+vhost_kill 0
+notice "Remove $aio_file"
+rm -f $aio_file
+
+python3 $testdir/windows_scsi_compliance.py
+if ! $keep_results_dir; then
+ rm -rf $testdir/results
+fi