仮想マシンをシャットダウンして、バックアップして、再び起動するというスクリプトを作ってみた。
標準ではPowershellからVMを操作するコマンドはなぜか用意されていない。
そこで、PowershellからVMを操作するにはWMIを使用するか、CodePlexで提供されているツールを使うか、システムセンターを使うかなのだそうだ。
ここらへんの話は以下の記事で詳しく解説してある。
【ハウツー】【管理効率化への挑戦】PowerShellで仮想環境も管理!! Hyper-V、SCとの連携 (1) Hyper-Vマネージャの問題点 | エンタープライズ | マイコミジャーナル
今回はバリバリ仮想マシンを操作するわけではないので、追加モジュールの必要ないWMIを使うことにした。
function main { $ErrorActionPreference = "STOP" $VMName = "GSG-SVV2" $VMQuery = "SELECT * FROM Msvm_ComputerSystem WHERE ElementName='$($VMName)'" $VMObj = gwmi -Query $VMQuery -Namespace "root\virtualization" -Computername "." Write-Output "■仮想マシン($($VMName))バックアップ開始:$(Get-Date)▼▼▼▼▼▼▼▼" if($VMObj.EnabledState -eq 2) { shutdown-vm Start-Sleep 300 } bkupcopy startup-vm Write-Output "■仮想マシン($($VMName))バックアップ終了:$(Get-Date)▼▼▼▼▼▼▼▼" trap{ Send-MailMessage -To "<vmuser@hoge.co.jp>" ` -From "VMServer <admin@hoge.co.jp>" ` -Subject "VM Bkup Error" ` -SmtpServer "smtp.hoge.co.jp" ` -Body "仮想マシン($($VMName))バックアップエラー" ` -Encoding ([System.Text.Encoding]::Default) } } function shutdown-vm { $STDObjQuery = "SELECT * FROM Msvm_ShutdownComponent WHERE SystemName='$($VMObj.name)'" $STDObj = gwmi -Query $STDObjQuery -Namespace "root\virtualization" -Computername "." $Result = $STDObj.InitiateShutdown($true,"バックアップ") } function bkupcopy { $gen = [Math]::Floor(((Get-Date).DayOfYear/7))%3 + 1 $bkupPath = "E:\仮想マシンバックアップ\gen$gen" if(Test-Path $bkupPath){cmd /C "rmdir /S /Q $bkupPath"} copy (Join-Path "D:\VM" $VMName) $bkupPath -force -Recurse } function startup-vm { $VMObj.RequestStateChange(2) } . main >> c:\log\仮想マシンバックアップ.log 2>&1 |
毎週末に実行し、3世代管理することとした。(年初からの日数で週数を求めて世代としている)
コピーする前に前回のコピーをクリアしているのだが、PowershellのRemove-Itemを使うとなぜか上手く行かなかった。
どうも、非同期に動作して次行のCopyとぶつかるような動作をしてしまうのだ。
それで止む無くDOSコマンドを使ってクリアしている。
仮想マシンのステータスはこんな感じらしい。
Enabled (Turns the VM on) : 2
Disabled (Turns the VM off) : 3
Reboot (A hard reset of the VM) : 10
Reset (For future use) : 11
Paused (Pauses the VM) : 32768
Suspended (Saves the state of the VM) : 32769
起動時はこのステータスを2にしてあげれば良いのだが、シャットダウンは3にすれば良いというものでもないらしい。
(シャットダウンオブジェクトを取得してそのメソッドを呼び出している)
また、シャットダウンは非同期に動くようなのでとりあえずSleepを噛ませている。