Hyper-V の自動バックアップ(エクスポート) スクリプト
次の機能を実装しています。Hyper-vのエクスポート(export)機能を利用した簡易Backupツールです。
- 指定した任意のバーチャルマシンをエクスポートできます。(複数指定可能)
- 実行中のバーチャルマシンは状態を保存に遷移させてからエクスポートします。
エクスポート後は、状態を実行中に戻します。
(エクスポート中は一時停止状態になりますがバーチャルマシン自体は再起動したりしません。) - ログに開始・終了時刻、エクスポート成否、エラーを出力します。
- タスクスケジューラから実行することができます。
以下のスクリプトを参考にして実装しました。
http://gallery.technet.microsoft.com/ScriptCenter/ja-jp/cb80c006-4602-410c-9871-a9883915e4b3
このツールでバックアップすると、指定したフォルダに仮想マシン名のサブフォルダが作成されバックアップが保存されます。
このツールは、2つのスクリプトファイル(hyper-v_export.vbs,config.txt)で構成されており、hyper-v_export.vbsは実行ファイルで変更の必要はありません。設定はconfig.txtの以下のキーで指定します。
CS_OUTPUT_FOLDER
エクスポートするフォルダを指定します。実行するとこのフォルダ下に仮想マシンの名前でサブフォルダが作成されバーチャルマシンがエクスポートされます。
CS_LOG_PATH
ログファイルのパスを指定します。
BackupVms
バックアップする仮想マシンの名称を設定します。(Hyper-Vマネージャで表示される仮想マシンの名前を指定してください)
以下にツールのダウンロードリンクと、設定ファイルを配置しますので確認してください。
config.txt
'
' Configuration Section
'
Const CS_OUTPUT_FOLDER = "E:\Export"
Const CS_LOG_PATH = "E:\Export.log"Dim BackupVms(1)
BackupVms(0) = "Windows7"
BackupVms(1) = "Windows2008R2"
hyper-v_export.vbs
option explicit
dim objfs:set objfs = createobject("scripting.filesystemobject"):sub include(p):executeglobal objfs.OpenTextfile(p).readall:end subdim objWScript
Set objWScript = CreateObject("WScript.Shell")dim strScriptPath
strScriptPath = objfs.GetParentFolderName(WScript.ScriptFullName)include(objFs.BuildPath(strScriptPath, "config.txt"))
dim managementService
const JobStarting = 3
const JobRunning = 4
const JobCompleted = 7
const wmiStarted = 4096
const wmiSuccessful = 0const vm_state_pause = 32769
const vm_state_start = 2
const vm_state_stop = 3const phase_sleep_time = 2000
const phase_wait_limit = 300dim objWMIService
set objWMIService = GetObject("winmgmts:\\.\root\virtualization")Main()
Sub Main()
Dim backupItem
Dim VMName
Dim VMList
Dim VM
Dim WaitResultFor Each VMName In BackupVms
Set VMList = objWMIService.ExecQuery("SELECT * FROM Msvm_ComputerSystem WHERE ElementName='" & VMName & "'")For Each VM In VMList
dim saveState
saveState = VM.EnabledState
if VM.EnabledState = vm_state_pause Or VM.EnabledState = vm_state_start Or VM.EnabledState = vm_state_stop Then
if VM.EnabledState = vm_state_start then
' 一時停止
VM.RequestStateChange(vm_state_pause)
WaitResult = WaitStateChange(VMName, vm_state_pause)
else
WaitResult = True
end ifif WaitResult = True Then
' エクスポート
Call ExportVirtualMachine(VMName)
WScript.Sleep(phase_sleep_time * 5)
if saveState = vm_state_start then
' 再開
VM.RequestStateChange(vm_state_start)
WaitResult = WaitStateChange(VMName, vm_state_start)
if WaitResult = False Then
WriteLog Format1("Name:{0} 仮想マシンを再開できませんでした。", VMName)
End If
end ifElse
WriteLog Format1("Name:{0} 仮想マシンを一時停止できませんでした。", VMName)
End If
else
WriteLog Format1("Name:{0} 仮想マシンの状態がオン、オフ、保存以外の場合はエクスポートできません。", VMName)
end ifNext
Next
End Sub
Function WaitStateChange(vmName, state)
dim waitIndex
dim VMList
waitIndex = 0
Do While waitIndex < phase_wait_limitSet VMList = objWMIService.ExecQuery("SELECT * FROM Msvm_ComputerSystem WHERE ElementName='" & VMName & "'")
if VMList.ItemIndex(0).EnabledState = state then
exit do
end ifWScript.Sleep(phase_sleep_time)
waitIndex = waitIndex + 1
LoopWaitStateChange = Not (waitIndex = phase_wait_limit)
End Function'-----------------------------------------------------------------
' Main
'-----------------------------------------------------------------
Sub ExportVirtualMachine(vmName)WriteLog Format1("Name:{0} Start Export Virtual Machine", vmName)
dim objArgs, vm, exportDirectory
set objfs = Wscript.CreateObject("Scripting.FileSystemObject")
set managementService = objWMIService.ExecQuery("select * from Msvm_VirtualSystemManagementService").ItemIndex(0)
exportDirectory = CS_OUTPUT_FOLDER
set vm = GetComputerSystem(vmName)if ExportVirtualSystem(vmName, vm, exportDirectory) then
WriteLog Format1("Name:{0} Done Success", vmName)
else
WriteLog Format1("Name:{0} ExportVirtualSystem Failed.", vmName)
end ifEnd Sub
'-----------------------------------------------------------------
' Retrieve Msvm_VirtualComputerSystem from base on its ElementName
'-----------------------------------------------------------------
Function GetComputerSystem(vmName)
On Error Resume Next
dim query
query = Format1("select * from Msvm_ComputerSystem where ElementName = '{0}'", vmName)
set GetComputerSystem = objWMIService.ExecQuery(query).ItemIndex(0)
if (Err.Number <> 0) then
WriteLog Format2("Name:{0} Err.Number: {1}", Err.Number, vmName)
WriteLog Format2("Name:{0} Err.Description:{1}",Err.Description, vmName)
WScript.Quit(1)
end if
End Function'-----------------------------------------------------------------
' Define a virtual system
'-----------------------------------------------------------------
Function ExportVirtualSystem(vmName, computerSystem, exportDirectory)dim objInParam, objOutParams
ExportVirtualSystem = falsedim vmPath
vmPath = objFs.BuildPath(exportDirectory, vmName)if objfs.FolderExists(vmPath) then
objfs.DeleteFolder(vmPath)
end if
WScript.Sleep(5000)if Not objfs.FolderExists(exportDirectory) then
objfs.CreateFolder(exportDirectory)
end if
set objInParam = managementService.Methods_("ExportVirtualSystem").InParameters.SpawnInstance_()objInParam.ComputerSystem = computerSystem.Path_.Path
objInParam.CopyVmState = true
objInParam.ExportDirectory = exportDirectory
set objOutParams = managementService.ExecMethod_("ExportVirtualSystem", objInParam)if objOutParams.ReturnValue = wmiStarted then
if (WMIJobCompleted(vmName, objOutParams)) then
ExportVirtualSystem = true
end if
elseif (objOutParams.ReturnValue = wmiSuccessful) then
ExportVirtualSystem = true
else
WriteLog Format2("Name:{0} DefineVirtualSystem failed with ReturnValue {1}", vmName, objOutParams.ReturnValue)
end ifEnd Function
'-----------------------------------------------------------------
' Handle wmi Job object
'-----------------------------------------------------------------
Function WMIJobCompleted(vmName, outParam)
dim WMIJob, jobStateset WMIJob = objWMIService.Get(outParam.Job)
WMIJobCompleted = true
jobState = WMIJob.JobState
while jobState = JobRunning or jobState = JobStarting
WScript.Sleep(1000)
set WMIJob = objWMIService.Get(outParam.Job)
jobState = WMIJob.JobState
wendif (jobState <> JobCompleted) then
WriteLog Format2("Name:{0} ErrorCode:{1}", vmName, WMIJob.ErrorCode)
WriteLog Format2("Name:{0} ErrorDescription:{1}", vmName, WMIJob.ErrorDescription)
WMIJobCompleted = false
end ifEnd Function
'-----------------------------------------------------------------
' Create the console log files.
'-----------------------------------------------------------------
Sub WriteLog(line)
dim fileStream
set fileStream = objfs.OpenTextFile(CS_LOG_PATH , 8, true)
fileStream.WriteLine CStr(Now()) & vbTab & 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