Hyper-Vのスナップショットを古い方から削除するスクリプト

Hyper-Vを稼働させていて、自動スナップショットを何度か行っていると気が付く事があります。スナップショットを消す場合、最新のスナップショットデータを消すのはMsvm_PreviousSettingDataがあるから楽なのですが、逆に一番古いスナップショットを消す場合は?と言われると困ってしまうわけです。

というわけで、自分自身必要に狩られたので先輩プログラマに聞きつつ作ってみました。動作的には各スナップショットの名前に自動的に付く時間から一番古いスナップショットを探していますので、スナップショット名を変更すると正常に動作しません。

やり方が強引なので、利用するのであれば動作確認してからでお願いしますね。

使い方はMSDNのサンプルと同じで

cscript RemoveVirtualSystemSnapshot.vbs vmName

です。

option explicit

dim objWMIService
dim managementService
dim fileSystem

const JobStarting = 3
const JobRunning = 4
const JobCompleted = 7
const wmiStarted = 4096
const wmiSuccessful = 0

Main()

'-----------------------------------------------------------------
' Main
'-----------------------------------------------------------------
Sub Main()
    dim computer, objArgs, vmName, vm, snapshotSetting

    set fileSystem = Wscript.CreateObject("Scripting.FileSystemObject")
    computer = "."
    set objWMIService = GetObject("winmgmts:\\" & computer & "\root\virtualization")
    set managementService = objWMIService.ExecQuery("select * from Msvm_VirtualSystemManagementService").ItemIndex(0)

    set objArgs = WScript.Arguments
    if WScript.Arguments.Count = 1 then
        vmName = objArgs.Unnamed.Item(0)
    else
        WScript.Echo "usage: cscript RemoveVirtualSystemSnapshot.vbs vmName"
        WScript.Quit(1)
    end if

    set vm = GetComputerSystem(vmName)
    set snapshotSetting = GetComputerSystemSnapshotSettings(vm)
'MsgBox snapshotSetting.ElementName
'WScript.Quit(0)

    if RemoveVirtualSystemSnapshot(snapshotSetting) then
        WriteLog "Done"
        WScript.Quit(0)
    else
        WriteLog "RemoveVirtualSystemSnapshot Failed."
        WScript.Quit(1)
    end if
End Sub

'-----------------------------------------------------------------
' Retrieve Msvm_VirtualComputerSystem from base on its ElementName
'-----------------------------------------------------------------
Function GetComputerSystem(vmElementName)
    On Error Resume Next
    dim query
    query = Format1("select * from Msvm_ComputerSystem where ElementName = '{0}'", vmElementName)
    set GetComputerSystem = objWMIService.ExecQuery(query).ItemIndex(0)
    if (Err.Number <> 0) then
        WriteLog Format1("Err.Number: {0}", Err.Number)
        WriteLog Format1("Err.Description:{0}",Err.Description)
        WScript.Quit(1)
    end if
End Function

'-----------------------------------------------------------------
' Retrieve the oldest Msvm_VirtualComputerSystem snapshot
'-----------------------------------------------------------------
Function GetComputerSystemSnapshotSettings(computerSystem)
    On Error Resume Next
    dim query

'    query = Format1("ASSOCIATORS OF {{0}} WHERE resultClass = Msvm_VirtualSystemsettingData AssocClass = Msvm_PreviousSettingData", computerSystem.Path_.Path)
     query = Format1("ASSOCIATORS OF {{0}} WHERE resultClass = Msvm_VirtualSystemsettingData", computerSystem.Path_.Path)

Dim i
Dim MinTimeNo
MinTimeNo = -1

For i = 0 To objWMIService.ExecQuery(query).Count - 1
    If InStr(objWMIService.ExecQuery(query).ItemIndex(i).ElementName,")") > 0 AND InStr(objWMIService.ExecQuery(query).ItemIndex(i).ElementName,"(") > 0 Then

'        MsgBox objWMIService.ExecQuery(query).ItemIndex(i).ElementName  & "--" & Left(objWMIService.ExecQuery(query).ItemIndex(i).CreationTime,14) & "-" & objWMIService.ExecQuery(query).ItemIndex(i).SettingType

        If MinTimeNo = -1 Then
            MinTimeNo = i
        Else
            If Left(objWMIService.ExecQuery(query).ItemIndex(MinTimeNo).CreationTime,14) > Left(objWMIService.ExecQuery(query).ItemIndex(i).CreationTime,14) Then
                MinTimeNo = i
            End if
        End If
    End If
Next

'MsgBox objWMIService.ExecQuery(query).ItemIndex(MinTimeNo).ElementName  & "--" & Left(objWMIService.ExecQuery(query).ItemIndex(MinTimeNo).CreationTime,14)

    set GetComputerSystemSnapshotSettings = objWMIService.ExecQuery(query).ItemIndex(MinTimeNo)
    if (Err.Number <> 0) then
        WriteLog Format1("Err.Number: {0}", Err.Number)
        WriteLog Format1("Err.Description:{0}",Err.Description)
        WScript.Quit(1)
    end if
End Function

'-----------------------------------------------------------------
' Revmove a virtual system Snapshot
'-----------------------------------------------------------------
Function RemoveVirtualSystemSnapshot(snapshotSettingData)

    dim objInParam, objOutParams

    RemoveVirtualSystemSnapshot = false
    set objInParam = managementService.Methods_("RemoveVirtualSystemSnapshot").InParameters.SpawnInstance_()
    objInParam.SnapshotSettingData = snapshotSettingData.Path_.Path

    set objOutParams = managementService.ExecMethod_("RemoveVirtualSystemSnapshot", objInParam)

    if objOutParams.ReturnValue = wmiStarted then
        if (WMIJobCompleted(objOutParams)) then
            RemoveVirtualSystemSnapshot = true
        end if
    elseif objOutParams.ReturnValue = wmiSuccessful then
        RemoveVirtualSystemSnapshot = true
    else
        WriteLog Format1("RemoveVirtualSystemSnapshot failed with ReturnValue {0}", objOutParams.ReturnValue)
    end if

End Function

'-----------------------------------------------------------------
' Handle wmi Job object
'-----------------------------------------------------------------
Function WMIJobCompleted(outParam)

    dim WMIJob, jobState
    WMIJobCompleted = true

    set WMIJob = objWMIService.Get(outParam.Job)

    jobState = WMIJob.JobState

    while jobState = JobRunning or jobState = JobStarting
        WriteLog Format1("In progress... {0}% completed.",WMIJob.PercentComplete)
        WScript.Sleep(1000)
        set WMIJob = objWMIService.Get(outParam.Job)
        jobState = WMIJob.JobState
    wend

    if (WMIJob.JobState <> JobCompleted) then
        WriteLog Format1("ErrorDescription:{0}", WMIJob.ErrorDescription)
        WriteLog Format1("ErrorCode:{0}", WMIJob.ErrorCode)
        WMIJobCompleted = false
    end if

End Function

'-----------------------------------------------------------------
' Create the console log files.
'-----------------------------------------------------------------
Sub WriteLog(line)
    dim fileStream
    set fileStream = fileSystem.OpenTextFile(".\RemoveVirtualSystemSnapshot.log", 8, true)
    WScript.Echo line
    fileStream.WriteLine line
    fileStream.Close
End Sub

'------------------------------------------------------------------------------
' The string formating functions to avoid string concatenation.
'------------------------------------------------------------------------------
Function Format2(myString, arg0, arg1)
    Format2 = Format1(myString, arg0)
    Format2 = Replace(Format2, "{1}", arg1)
End Function

'------------------------------------------------------------------------------
' The string formating functions to avoid string concatenation.
'------------------------------------------------------------------------------
Function Format1(myString, arg0)
    Format1 = Replace(myString, "{0}", arg0)
End Function

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です