Here's an example of a script written in VBScript that you can write to perform a warm backup of a virtual machine. It was written by John Kelbley, who's a technology specialist for Microsoft. Please pay attention to the warnings and caveats given in the script.
Thanks John!
' READ THIS LINE!!! The sample scripts are not supported under any Microsoft standard support program or service. The sample scripts are provided AS IS without warranty of any kind. Microsoft further disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages. ''' MoveWarm.VBS written by John Kelbley ''' This the mother of all Demo Virtual Server Availability scripts! '' When the script is executed properly from a running Virtual Server system with active Guest images,' it hibernates, copies, installs, and starts all active Guest images on another Virtual Server! '' This could be used in a production environment to allow for hardware maintenance while minimizing down time of Guest images, if all assumptions are met, including:' Identical Virtual Server hardware configuration - enough RAM, disk space with same drive letters, etc. on target to accommodate migrated guest images' Identical Virtual Network configuration (it's just easier, otherwise, they may not start automatically, and you'll have to adjust the config)' Other things I haven't run into in my testing (I only have a couple of Evo's to test on!)' XP SP2 (connection firewall) can keep this from running, depending on the hosts you are using (rumor that some DCOM security thing might mess things up, too)' I sometimes have been know to setup a local account on both hosts with the same name and password as my domain credential, and map drives back and forth to ' make sure everything will run right before kicking off the script for a demo!'' NAME RESOLUTION IS A BIG DEAL HERE TOO!!!'' How does the Script do it? It does a few key things:' 1) "saves state" on running VPC images' 2) Creates a .BAT and .VBS on original host for each of the hibernated images in current directory' 3) Starts .BAT for each hibernated image on local host (this kind of multi-threads the copy)' a) copies files related to image to new host (.VHD config, save state)' b) runs .VBS to register config file on new host, and re-start from Saved State'' The script does not clean up after itself, as it is a sample meant for training purposes!'' The .BAT and .VBS files generated may be of interest to someone, so at this time, I did not want to delete them''' When I run the demos, I usually use smaller VMs - some from the VMSTORE areas - like Windows 3.0 or BOB on Windows 95''' Thanks to the Tech Net Script Center folks for all their guidance (great examples on the web, as well as usable reference books on VBS!)''Option Explicit'On Error Resume Next
Const ForWriting = 2 ' constant used for openning text files
Dim ToSystem ' Computer Name of Target host systemDim FromSystem ' Computer Name of source host systemDim VMStateCodes ' Array of VM State Codes - to display kinder status that integersDim VMStuff ' Virtual Server Info instanceDim SourcevmCollection ' Collection of VMs from Source ServerDim vm ' instance of a VM from collection loopDim objVM ' instance of a VMDim MoveVM ' instance of a VMDim colHardDisks ' Collection of VHDs in a VMDim objDrive ' instance of a VHD from collection loopDim objHardDisk ' instance of a VHDDim NameLength ' for tidy display of VM namesDim MaxNameLength ' for tidy display of VM namesDim VMCount ' counter for all VMs Dim MoveCount ' counter for VMs to move - VMs that are currently running (nicer demo!)Dim MoveName ' local var with VM name Dim VMInfo(100) ' array of VM names to be movedDim TargetHost ' The server where all the runnning VM's will be movedDim TargetHostServer ' The server where all the runnning VM's will be movedDim TargetHostAvailable ' Boolean to track if the target host is pingableDim MyShell ' Used to find local host name, if requiredDim MyEnvironment ' Used to find local host name, if required
' Set Target host variables'TargetHost = "192.168.0.3" ' put name or IP Address of target server here, NOT preceeded by two slashes'TargetHost = "WS03VS01" ' put name or IP Address of target server here, NOT preceeded by two slashesTargetHost = "CHANGEME" ' put name or IP Address of target server here, NOT preceeded by two slashes
'' Should not need to change anything after here to get script to run!'TargetHostServer = "\\" & TargetHostTargetHostAvailable = TRUE ' setting default before ping test
Call Housekeeping()
VMCount = 0Set SourcevmCollection = VMStuff.VirtualMachines '' Get maximum Name Length for Formatting - just makes some things look nice'For each vm in SourcevmCollection NameLength = Len(vm.Name) If MaxNameLength < NameLength Then MaxNameLength = NameLength End If ' ' If VM is "Running" them target for WARM migration to other host system ' Here is where the systems are identifed at migration targets ' if VMStateCodes(vm.State) = "Running" Then VMInfo(VMCount) = vm.Name VMCount = VMCount + 1 End IfNext
For each vm in SourcevmCollection Wscript.Echo VbCrLf & "--------------------------------------------------------------------" Wscript.Echo " " & vm.Name & Space(MaxNameLength - Len(vm.Name)) & " - State is: " & VMStateCodes(vm.State)Next
Wscript.Echo VbCrLf & "--------------------------------------------------------------------" Wscript.Echo "--------------------------------------------------------------------" if VMCount = 0 then Wscript.Echo VbCrLf & "No VMs are runnning, nothing to warm move"End If
'****************************************************' Engine is here!!!!!'****************************************************if TargetHostAvailable = TRUE Then For MoveCount = 1 to VMCount MoveName = VMInfo(MoveCount-1) Wscript.Echo "Processing " & MoveName & Space(MaxNameLength - Len(MoveName)) & " VM " & MoveCount & " of " & VMCount & "..." Set objVM = VMStuff.FindVirtualMachine(MoveName)
' Save State of all running VMs Call SaveVMState(MoveName)
' Generage .BAT and .VBS for each of the running VMs Call MakeScriptFiles(MoveName)
Wscript.Echo VbCrLf & "--------------------------------------------------------------------" NextEnd If
Wscript.Echo VbCrLf & "--------------------------------------------------------------------" Wscript.Echo "--------------------------------------------------------------------" 'End Script
'******************************************************************************'******************************************************************************'******************************************************************************'******************************************************************************'* *'* *'* Subroutines to make the stuff up top look nicer! *'* *'* *'* *'******************************************************************************'******************************************************************************'******************************************************************************'******************************************************************************
'******************************************************************************'* *'* Do some if the ugly stuff that I didn't want to put at the front *'* of the script *'* *'******************************************************************************Sub Housekeeping()
Dim objPing ' use for ping test - poached from TechNet examples Dim objStatus ' use for ping test - poached from TechNet examples
Wscript.Echo VbCrLf & "--------------------------------------------------------------------" Wscript.Echo VbCrLf & "- -" Wscript.Echo VbCrLf & "- -" Wscript.Echo VbCrLf & "- WarmMove.VBS -" Wscript.Echo VbCrLf & "- -" Wscript.Echo VbCrLf & "- by -" Wscript.Echo VbCrLf & "- -" Wscript.Echo VbCrLf & "- John Kelbley -" Wscript.Echo VbCrLf & "- -" Wscript.Echo VbCrLf & "- -" Wscript.Echo VbCrLf & "- Finds running VM's running under Virtual Server 2005 -" Wscript.Echo VbCrLf & "- on local system, pauses them, moves them to specified target -" Wscript.Echo VbCrLf & "- and unpauses them! -" Wscript.Echo VbCrLf & "- -" Wscript.Echo VbCrLf & "- Please read comments in script carefully before running! -" Wscript.Echo VbCrLf & "- -" Wscript.Echo VbCrLf & "- This is a sample, and is not meant for use in production. -" Wscript.Echo VbCrLf & "- -" Wscript.Echo VbCrLf & "- Script expects NO paramameter - the name of the target -" Wscript.Echo VbCrLf & "- Virtual Server host is specified internally -" Wscript.Echo VbCrLf & "- (I WANT YOU TO LOOK AT THE SCRIPT!!!!) -" Wscript.Echo VbCrLf & "- -" Wscript.Echo VbCrLf & "- -" Wscript.Echo VbCrLf & "- Example: cscript MoveWarm.VBS -" Wscript.Echo VbCrLf & "- -" Wscript.Echo VbCrLf & "- -" Wscript.Echo VbCrLf & "- -" Wscript.Echo VbCrLf & "--------------------------------------------------------------------"
' Populate VM State Array VMStateCodes = Array("Invalid", "Turned Off","Saved","Turning On", "Restoring", "Running", "Paused", "Saving",_ "Turning Off", "Merging Drives", "Deleting Machine")
' Create VS application instance Set VMStuff = WScript.CreateObject("VirtualServer.Application")
Wscript.Echo VbCrLf & "Source Host System (this box!): " & FromSystem
Wscript.Echo VbCrLf & "--------------------------------------------------------------------"
Wscript.Echo "Default VM configuration path: " & VMStuff.DefaultVMConfigurationPath Wscript.Echo "Default VN configuration path: " & VMStuff.DefaultVNConfigurationPath
' Check to see if remote target system is accessible... ' Wscript.Echo VbCrLf & "Pinging " & TargetHost & " to see if warm migration can occour..." Set objPing = GetObject("winmgmts:{impersonationLevel=impersonate}").ExecQuery("select * from Win32_PingStatus where address = '" & TargetHost & "'") For Each objStatus in objPing If IsNull(objStatus.StatusCode) or objStatus.StatusCode<>0 Then TargetHostAvailable = FALSE WScript.Echo VbCrLf & "machine " & TargetHost & " is not reachable" WScript.Echo "CANNOT EXECUTE Warm migration" & VbCrLf End If Next '*********************************************************************************** ' should add a check to see if remote system has Virual Server installed, too!!!!! '***********************************************************************************End Sub
'******************************************************************************'* *'* Saves the State of Running VMs - creating a "hibernated" VM *'* *'******************************************************************************Sub SaveVMState(subVMName) Wscript.Echo Space(MaxNameLength + 12) & "Saving State" While objVM.State > 2 ' if the VM is not turned off of saved... if VMStateCodes(objVM.State) = "Running" Then objVM.Save() End If wscript.sleep(1000) Wscript.Echo Space(MaxNameLength + 12) & VMStateCodes(objVM.State) WendEnd Sub
'******************************************************************************'* *'* Generate .BAT and .VBS files to handle the migration of VM files *'* *'******************************************************************************Sub MakeScriptFiles(subVMName)
Dim LocalBatchFile Dim LocalVBSFile Dim LocalFSO Dim LocalFile Dim FileFSO Dim FileToCheck Dim FoundFolder Dim FromFileConfig Dim ToFileConfig Dim ConfigFolder Dim FromFileState Dim ToFileState Dim FromFileVHD Dim ToFileVHD Dim FromFileVUD Dim ToFileVUD Dim CommandString Dim objShell
Set MoveVM = VMStuff.FindVirtualMachine(subVMName) Wscript.Echo VbCrLf & "Beginning Move Processing..."
' *********************************************************************************************************************** ' *********************************************************************************************************************** ' code to create .BAT to copy files and call .VBS to register config file and start image ' *********************************************************************************************************************** ' *********************************************************************************************************************** LocalVBSFile = subVMName & "_" & "local.vbs" LocalBatchFile = subVMName & "_" & "local.bat"
Set LocalFSO = CreateObject ("scripting.FileSystemObject") Set LocalFile = LocalFSO.CreateTextFile(LocalBatchFile)
' start writing batch file LocalFile.WriteLine "@Echo off" LocalFile.WriteLine "Echo ---------------------------------------------------------"
' Construct destination UNC for Config File to copy ' Need the path for the parent directory of the file to copy to make Xcopy work right...this seemed easier than parsing the string! FromFileConfig = MoveVM.File Set FileFSO = CreateObject("Scripting.FileSystemObject") Set FileToCheck = FileFSO.GetFile(FromFileConfig) FoundFolder = FileFSO.GetParentFolderName(FileToCheck) ConfigFolder = FoundFolder ' Saving this for the VBS later... ToFileConfig = TargetHostServer & "\" & Left(FoundFolder, 1) & "$" & Mid(FoundFolder, 3, 1024) CommandString = "xcopy " & CHR(34) & FromFileConfig & CHR(34) & " " & CHR(34) & ToFileConfig & "\" & CHR(34) & " /Y" LocalFile.WriteLine "echo Copying " & FromFileConfig & " to remote, please wait..." LocalFile.WriteLine CommandString LocalFile.WriteLine "Echo ---------------------------------------------------------"
' Construct destination UNC for Save State File n FromFileState = MoveVM.SavedStateFilePath Set FileFSO = CreateObject("Scripting.FileSystemObject") Set FileToCheck = FileFSO.GetFile(FromFileState) FoundFolder = FileFSO.GetParentFolderName(FileToCheck) ToFileState = TargetHostServer & "\" & Left(FoundFolder , 1) & "$" & Mid(FoundFolder, 3, 1024) CommandString = "xcopy " & CHR(34) & FromFileState & CHR(34) & " " & CHR(34) & ToFileState & "\" & CHR(34) & " /Y" LocalFile.WriteLine "echo Copying " & FromFileState & " to remote, please wait..." LocalFile.WriteLine CommandString LocalFile.WriteLine "Echo ---------------------------------------------------------"
' Take Care of VHD (drive image) and VUD files (undo files) - can be more than one for a Guest... Set colHardDisks = MoveVM.HardDiskConnections For Each objDrive in colHardDisks FromFileVHD = objDrive.HardDisk.File Set FileFSO = CreateObject("Scripting.FileSystemObject") Set FileToCheck = FileFSO.GetFile(FromFileVHD) FoundFolder = FileFSO.GetParentFolderName(FileToCheck) ToFileVHD = TargetHostServer & "\" & Left(FoundFolder, 1) & "$" & Mid(FoundFolder, 3, 1024) CommandString = "xcopy " & CHR(34) & FromFileVHD & CHR(34) & " " & CHR(34) & ToFileVHD & "\" & CHR(34) & " /Y" LocalFile.WriteLine "echo Copying " & FromFileVHD & " to remote, please wait...(big file!)" LocalFile.WriteLine CommandString LocalFile.WriteLine "Echo ---------------------------------------------------------" If MoveVM.Undoable Then FromFileVUD = objDrive.UndoHardDisk.File Set FileFSO = CreateObject("Scripting.FileSystemObject") Set FileToCheck = FileFSO.GetFile(FromFileVUD) FoundFolder = FileFSO.GetParentFolderName(FileToCheck) ToFileVUD = TargetHostServer & "\" & Left(FoundFolder, 1) & "$" & Mid(FoundFolder, 3, 1024) CommandString = "xcopy " & CHR(34) & FromFileVUD & CHR(34) & " " & CHR(34) & ToFileVUD & "\" & CHR(34) & " /Y" LocalFile.WriteLine "echo Copying " & FromFileVUD & " to remote, please wait..." LocalFile.WriteLine CommandString LocalFile.WriteLine "Echo ---------------------------------------------------------" End If Next
' Call .VBS to register configuration file and start the VPC image LocalFile.WriteLine "Echo Calling script to register config file on remote and start VM..." LocalFile.WriteLine "CScript " & CHR(34) & LocalVBSFile & CHR(34) & " //NoLogo"
LocalFile.WriteLine "Echo End of Batch file" LocalFile.WriteLine "Echo ---------------------------------------------------------" LocalFile.Close 'close batch file
' *********************************************************************************************************************** ' *********************************************************************************************************************** ' code to create .VBS to register config file with Target Virtual Server ' *********************************************************************************************************************** ' *********************************************************************************************************************** Set LocalFSO = CreateObject ("scripting.FileSystemObject") Set LocalFile = LocalFSO.CreateTextFile(LocalVBSFile)
' start writing .VBS file ' LocalFile.WriteLine "On Error Resume Next" LocalFile.WriteLine "Set objVS = CreateObject(" & CHR(34) & "VirtualServer.Application" & CHR(34) & ", " & CHR(34) & TargetHostServer & CHR(34) & ")" LocalFile.WriteLine "errReturn = objVS.RegisterVirtualMachine(" & CHR(34) & subVMName & CHR(34) & "," & CHR(34) & ConfigFolder & CHR(34) & ")" LocalFile.WriteLine "Set objVM = objVS.FindVirtualMachine(" & CHR(34) & subVMName & CHR(34) & ")" LocalFile.WriteLine "objVM.Startup()"
LocalFile.Close 'close .VBS file Set objShell = Wscript.CreateObject("Wscript.Shell") CommandString = "%comspec% /c " & CHR(34) & LocalBatchFile & CHR(34) Wscript.Echo VbCrLf & "Command string: " & CommandString objShell.Run(CommandString)
Wscript.Echo VbCrLf & "End Move Processing"End Sub