稼動している全てのゲストOSのスナップショットを古い方から削除する@Hyper-V

以前記載したスクリプトを無理やり起動している全ての端末を対象に動作するように書き換えました。

ただしスナップショットをたくさん作るとゲストOSシャットダウン時に結合処理の実行が走るので、ガンガン取得したりガンガン消すのはもしかするとあまり良くないのかも知れないな・・・・なんて思いつつ、とりあえず動作すれば良いか的な部分もあります。

option explicit

dim objWMIService
dim managementService
dim fileSystem

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


Dim objWMI
Dim VM
Dim VMList
set fileSystem = Wscript.CreateObject("Scripting.FileSystemObject")
Set objWMI = GetObject("winmgmts:\\.\root\virtualization")

'日本語環境ではホストマシンのDescriptionが'Microsoft ホスト コンピュータ システム'となるのでそれをクエリで除外
Set VMList = objWMI.ExecQuery _
("SELECT * FROM Msvm_ComputerSystem Where Description = 'Microsoft Virtual Machine'")

'マシンステータスが2(起動中)だった場合にスナップショットを取得
For Each VM In VMList
	If VM.EnabledState = 2 Then
		WriteLog VM.ElementName
		Main(VM.ElementName)
	Else
		WriteLog Format1("{0} は起動していません。" , VM.ElementName)
	End If
Next

'-----------------------------------------------------------------
' Main
'-----------------------------------------------------------------
Sub Main(vmName)
    dim computer, 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 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

コメントを残す

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