test/vhost: windows scsi compliance test.
We don't provide windows executable for this test. Change-Id: Iedaafba06662f776c102528f8073b6c3d56bb323 Signed-off-by: Pawel Kaminski <pawelx.kaminski@intel.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/450406 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Karol Latecki <karol.latecki@intel.com> Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
7a1c568598
commit
4f31e10705
@ -250,6 +250,25 @@ function assert_number()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Run command on vm with given password
|
||||||
|
# First argument - vm number
|
||||||
|
# Second argument - ssh password for vm
|
||||||
|
#
|
||||||
|
function vm_sshpass()
|
||||||
|
{
|
||||||
|
vm_num_is_valid $1 || return 1
|
||||||
|
|
||||||
|
local 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 "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# Helper to validate VM number
|
# Helper to validate VM number
|
||||||
# param $1 VM number
|
# param $1 VM number
|
||||||
#
|
#
|
||||||
|
73
test/vhost/windows/windows_scsi_compliance.ps1
Normal file
73
test/vhost/windows/windows_scsi_compliance.ps1
Normal file
@ -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"
|
||||||
|
}
|
147
test/vhost/windows/windows_scsi_compliance.py
Executable file
147
test/vhost/windows/windows_scsi_compliance.py
Executable file
@ -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("(ASSERTION\s[1-9][\d+]?\.\d+\s)(.+\s)([\w\W]+?)(Result:\s)(\w+)", re.I | re.M)
|
||||||
|
scsi_2_pattern = re.compile("(?: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("\s+", "_", (m[0] + m[1]).strip())
|
||||||
|
test_name = re.sub("[():]", "", 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)
|
81
test/vhost/windows/windows_scsi_compliance.sh
Executable file
81
test/vhost/windows/windows_scsi_compliance.sh
Executable file
@ -0,0 +1,81 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
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="$testdir/aio_disk"
|
||||||
|
ssh_pass=""
|
||||||
|
vm_num=1
|
||||||
|
rpc_py="$rootdir/scripts/rpc.py -s $(get_vhost_dir)/rpc.sock"
|
||||||
|
|
||||||
|
function usage()
|
||||||
|
{
|
||||||
|
[[ ! -z $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"
|
||||||
|
|
||||||
|
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#*=}" ;;
|
||||||
|
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
|
||||||
|
|
||||||
|
mkdir -p $testdir/results
|
||||||
|
dd if=/dev/zero of=$aio_file bs=1M count=512
|
||||||
|
|
||||||
|
timing_enter spdk_vhost_run
|
||||||
|
spdk_vhost_run
|
||||||
|
$rpc_py set_bdev_nvme_hotplug -e
|
||||||
|
$rpc_py construct_malloc_bdev 256 4096 -b Malloc0
|
||||||
|
$rpc_py construct_aio_bdev $aio_file Aio0 512
|
||||||
|
$rpc_py get_bdevs
|
||||||
|
$rpc_py construct_vhost_scsi_controller naa.vhost.1
|
||||||
|
$rpc_py add_vhost_scsi_lun naa.vhost.1 0 Nvme0n1
|
||||||
|
$rpc_py add_vhost_scsi_lun naa.vhost.1 1 Malloc0
|
||||||
|
# TODO: Currently there is bug for aio device. Disable this test
|
||||||
|
# $rpc_py add_vhost_scsi_lun naa.vhost.1 2 Aio0
|
||||||
|
timing_exit spdk_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"
|
||||||
|
spdk_vhost_kill
|
||||||
|
notice "Remove $aio_file"
|
||||||
|
rm -f $aio_file
|
||||||
|
|
||||||
|
python3 $testdir/windows_scsi_compliance.py
|
||||||
|
rm -rf $testdir/results
|
Loading…
Reference in New Issue
Block a user