如何讓 HyperV 中設定 VM 的 AllowFullSCSICommandSet - 2012R2 ver
問題
在 2008 中可以透過 powershell 的方式來設定 VM 裡的 SCSI 設定值 AllowFullSCSICommandSet
$VMName=$args[0]
$VSManagementService=gwmi MSVM_VirtualSystemManagementService -namespace "root\virtualization"
foreach($Child in Get-WmiObject -Namespace root\virtualization Msvm_ComputerSystem -Filter "ElementName='$VMName'")
{
$VMData=Get-WmiObject -Namespace root\virtualization -Query "Associators of {$Child} Where ResultClass=Msvm_VirtualSystemGlobalSettingData AssocClass=Msvm_ElementSettingData"
$VMData.AllowFullSCSICommandSet=$true
$VSManagementService.ModifyVirtualSystem($Child,$VMData.PSBase.GetText(1))|out-null
}
但是相同的語法在 2012 R2 上卻會出現
「The property ‘AllowFullSCSICommandSet’ cannot be found on this object. Verify that the property exists and can be set」
而且會在黃色的部分出錯,從開發的角度來看,這很明顯是 VMData 的 Object 沒有正確的物件或是該屬性已經消失了。
因此從這裡開始了我在 VM PowerShell 的 Debug 之路
除錯
環境準備上強烈建議用 ISE 工具,因為 powershell 已經不單單只是一種 command 更是一種程式。所以有好的工具除錯是很重要的,還沒有用過的朋友可以加減參考一下。
大家都知道 2008 和 2012 Hyper V 的版本已經不同了,所以這個問題直覺就是認為一定是語法或是參數上有錯。重新查了資料後確定 MSVM_VirtualSystemManagementService 這個 Class 有 2008 和 2012 兩個版本,其 Namespace 多了 V2 。
https://msdn.microsoft.com/en-us/library/hh850253(v=vs.85).aspx
確認拿到的源頭物件無誤後,接下來就是逐一地驗證轉型,由於 powershell 的特性不會有強制型別的驗證,所以這裡是用較舊的方式用 ToString 來確認型別 ( 若 toString 被用掉的話可以改用 __CLASS 和 __PATH ) 。
為了好除錯,每一次轉型我都是單獨一行,以便可以確認型別和查其他的參數。
裡面最麻煩的部分就是要如何取得到 MSVM_VirtualSystemSettingData ,花了很多時間在確認機制和參數。
https://msdn.microsoft.com/en-us/library/hh850257(v=vs.85).aspx
結果
$VMName="SQL1_2012R2"
Write-Host "start"
$VSManagementService=gwmi Msvm_VirtualSystemManagementService -namespace "root\virtualization\v2"
$VM = gwmi Msvm_ComputerSystem -namespace "root\virtualization\v2" -Filter "elementName='$VMName'"
$VMData = $VM.GetRelated("MSVM_VirtualSystemSettingData") | Where-Object { $_.VirtualSystemType -eq 'Microsoft:Hyper-V:System:Realized'}
$VMData.AllowFullSCSICommandSet=$true
Write-Host "AllowFullSCSICommandSet" $VMData.AllowFullSCSICommandSet
$VSManagementService.ModifySystemSettings($VMData.PSBase.GetText(1))|out-null
Write-Host "end"
完成的項目畫面,可以看到指令完成無誤。