何かを行おうとすると別の何かを学ばないといけなくて結局遠回りしている気がする・・・・なんてのはザラにある気がしますが、今回のPowerShellもそんな感じ。
【目的】
タスクスケジューラに登録した定時に特定のゲストOSのスナップショットを作成し、同時に過去数日前のスナップショットをマージ(Apply)する
【手段】
Hyper-V上の操作となるのでWMI(Windows Management Instrumentation)を使用する、且つ、タスクスケジューラでの操作となるのでCUI(=スクリプト系)が望ましい。WMIが操作できるスクリプトはWSH, PowerShell辺りとなる・・・・はず?
【参考資料】
ほぼほぼ資料は集まっていて、以下を見れば私だってできるハズ!
- Hyper-V WMI: Creating/Applying/Deleting Virtual Machine Snapshots
- Virtual System Management Classes
- CIM_ConcreteJob class
という感じなのですが、手段としてPowerShellを選ぶと、目的を達成する前にPowerShellを覚えるところから始まるのですよね。元々WMI(WBEM)+JScriptで色々とごさごさやっていたので作れないことは無いですがやはりここはWindows2008らしくPowerShellで実装しないとね!
ただ・・・・、従来のMicrosoft系スクリプト言語とは結構違う・・・気が・・・。PowerShellのコンセプトを知らないし、PowerShellが出た当初はこんなのを使う必要はないだろう!、とか甘く見ていた自分が馬鹿だったなと。因みに今はどうなのでしょうね、MS系の製品と触れ合う現場ではないので正直PowerShellがいかほどに使われているかさっぱりわかりません。
なので・・・・・、とりあえず適当な戦利品。
$computer = "." $namespace = "root\virtualization" $msvm_computer_system = "Msvm_ComputerSystem" $msvm_virtual_system_management_service = "Msvm_VirtualSystemManagementService" # 仮想システムの管理サービスインスタンスを取得する $vm_vsms = Get-WmiObject -Namespace $namespace -Computer $computer -Class $msvm_virtual_system_management_service $vm_host = $vm_vsms.SystemName Write-Output $vm_vsms # Hyper-V上の全てのコンピュータを列挙する (但し、ホストは除く) $vm_computers = Get-WmiObject -Namespace $namespace -Computer $computer -Class $msvm_computer_system -Filter "ElementName <> '$vm_host'" #write-output($vm_computers) foreach ($vm_computer in $vm_computers) { write-host + $vm_computer.ElementName $Snapshots = Get-WmiObject -Namespace root\virtualization -Query "Associators Of {$vm_computer} Where AssocClass=Msvm_ElementSettingData ResultClass=Msvm_VirtualSystemSettingData" if ($Snapshots.Count -le 0) { continue; } $script:list = @() foreach ($Snapshot in $Snapshots) { $SnapObj = New-Object -TypeName System.Object $SnapObj | Add-Member -MemberType NoteProperty -Name SnapshotName -Value $Snapshot.ElementName $SnapObj | Add-Member -MemberType NoteProperty -Name SnapshotID -Value $Snapshot.InstanceID $SnapObj | Add-Member -MemberType NoteProperty -Name SnapshotParentName -Value ([WMI]$Snapshot.Parent).ElementName $SnapObj | Add-Member -MemberType NoteProperty -Name SnapshotNote -Value $Snapshot.Note $script:list += $SnapObj } $script:list <# $script = @{} foreach ($Snapshot in $Snapshots) { $SnapObj = New-Object -TypeName System.Object $SnapObj | Add-Member -MemberType NoteProperty -Name SnapshotName -Value $Snapshot.ElementName $SnapObj | Add-Member -MemberType NoteProperty -Name SnapshotID -Value $Snapshot.InstanceID $SnapObj | Add-Member -MemberType NoteProperty -Name SnapshotParentName -Value ([WMI]$Snapshot.Parent).ElementName $SnapObj | Add-Member -MemberType NoteProperty -Name SnapshotNote -Value $Snapshot.Note $script.Add($SnapObj.SnapshotName, $SnapObj); } $script.GetEnumerator() | Sort-Object Name | ForEach-Object {"{0}`t{1}" -f $_.Name,($_.Value -join ",")} #> write-output "" }
そして、実行のスクリーンショットらしき物体。
しかし・・・・こんなことなら牟田口さんの”Windows PowerShell ポケットリファレンス”を買っておけばよかった・・・・。まぁ、スクリプトが仕上がったら置くかもしれません。それまでしばちお待ちを。