VMをあるデータストアから別のデータストアに移動するスクリプトがあります。ストレージバックエンドとファブリックをオーバーサブスクリプションから保護し、特定の時間に新しいリクエストを送信するのを待つ他のロジックがあります(ビジネス要件)。私はデータストアを移動するだけで、ホストは移動しません。失敗を処理したいので、Move-VMの周りにtrycatchブロックがあります。スクリプトを実行した最初の2、3回は、わずかなエラーしか発生せず、期待どおりに処理されました。最後の5回の移動はエラーを返しますが、vCenterに表示されるタスクで示されるように、VM移動要求は成功します。このジョブも正常に完了します。Move-VMは、 RunAsyncスイッチ。Move-VMがエラーを返しても、移動要求を正常に送信する原因は何ですか。
$VMs = Get-VM -Name $ComputerName
$CurrentDataStores = Get-Datastore
foreach ($VM in $VMs){
foreach ($store in $CurrentDataStores){
if ($store.name -eq "$Datastore"){
$rawDatastore = $store
}
if ($store.id -Match $VM.DatastoreIdList){
$VMDatastore = $store.name
}
}
if ($VMDatastore -eq "$Datastore"){
Write-Output "$VM : is already on requested Datastore"
}
else{
try {
Move-VM -VM $VM -Datastore $rawDatastore -ErrorAction Stop
}
catch {
Write-OutPut "$VM : Unable to move VM to new Datastore"
continue
}
}
}
Move-VMDatastore : <VM Name> : Unable to move VM to new Datastore
At line:1 char:1
+ Move-VMDatastore -ComputerName <VM Name> -Datastore <Move TO Datastore>
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Move-VMDatastore
Move-VMDatastore : 12/24/2014 12:50:02 AM Move-VM Operation is not valid due to the current state of the
object.
At line:1 char:1
+ Move-VMDatastore -ComputerName <ComputerName[]> -Datastore <Datastore>
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Move-VMDatastore
この問題についての私の理解は、Move-VMの実装では、PowerCLIが非同期タスクを実行し、タスクを取得してから、そのタスクでWait-Task
を実行することです。
操作が非常に速い場合、この問題で失敗します。これは、完了したタスクをWait-Task
したときに発生する正確な例外であるという事実に起因する、知識に基づいた推測です。
つまり、基本的に問題は、VMwareサーバーが速すぎる...
回避策は、-RunAsyncスイッチを使用して、正しい動作を自分で実装することです。何かのようなもの:
$Task = Move-VM -VM $VM -Datastore $rawDatastore -ErrorAction Stop -RunAsync
while($true)
{
switch ($task.State)
{
'Success' { $Task.Result; break }
'Error' { throw $Task.ExtensionData.Info.Error.LocalizedMessage }
Start-Sleep 5
}
}
編集:Stop-VMとRemove-VMでまったく同じ問題が発生し、同じ方法で回避しました
この問題は、ここでPowerCLIチームに改善のために提出されました: https://powercli.ideas.aha.io/ideas/PCLI-I-208
他の誰かがこの問題に遭遇した場合に備えて、$ task変数はそれ自体では更新されないように見えます。私の場合、私はしなければなりませんでした:
while($task.state -eq "Running")
{
Start-Sleep 5
$task = Get-Task -ID $task.id
}