Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ' Copyleft saxa aka Alexander Kaufmann, 2007
- ' Written just for fun; total Open Source.
- ' Use it at your own risk.
- ' The script uses the VS API for the virtual machine operations.
- ' The virtual machine *must* have the Additions installed, in order to perform the
- ' shutdown and heartbeat operations correctly.
- 'On Linx guests, we need at least the shutdown and heartbeat packages, but they wouldn't run without the kernel package...
- ' DON'T APPLY THIS SCRIPT ON RUNNING VIRTUAL MACHINES WHICH DON'T HAVE THE ADDITIONS INSTALLED.
- ' The script doesn't use the NTBackup utility. It will work on all supported hosts, be it 32 or 64 bit.
- ' The script runs on the local host only; it cannot be used to connect to a remote Virtual Server.
- ' The script *can* backup to the network share, if you have the appropriate permissions to write on it.
- ' For the backup jobs it uses the command line version of 7zip. Download the full install of 7zip: if your host is 32bit,
- ' you'll need the 32bit version; for 64bit hosts please install the 64bit one.
- ' Install 7zip with defaults; the script will find it as it's needed.
- ' We assume that all of your virtual machine files are located in the appropriate subdirectories
- ' of *one* directory; in other words, we need a flat structure. Subfolders are OK.
- ' There are 3 methods of running the script.
- ' The first one - by double-clicking of it. You will be prompted for the name
- ' of the VM you want to backup and for the location of the .zip file.
- ' When the job is ready, you'll get the message.
- ' The second one is like
- ' "vs-backup.vbs "My Virtual Machine"" (or "wscript.exe vs-backup.vbs "My Virtual Machine"" if used in a scheduled task)
- ' It will backup your VM to the default location defined in the 'bkpath' variable
- ' and save your backup file as "My Virtual Machine-YYYY-MM-DD-HHMMSS.zip"
- '
- 'The third one is like
- ' "vs-backup.vbs "My Virtual Machine" "X:\Full\Path\To\My\Backup\File.zip""
- ' (or "wscript.exe vs-backup.vbs "My Virtual Machine" "X:\Full\Path\To\My\Backup\File.zip"" if used in a scheduled task)
- ' It will backup your VM to the file defined in the second parameter.
- ' The script does the following:
- ' The virtual machine receives the command to shut down it's operating system.
- ' The script waits 30 seconds and than checks the state of the virtual machine.
- ' If the vm still runs, the script waits 30 seconds more and so on.
- ' As soon as the vm is off, the script copies the vm's folder into the backup location.
- ' If the vm couldn't be shut down, the mail is sent to the admin,
- ' the error is written in the Windows application log.
- ' After the copying is done, the vm receives the command to start, if it was running before the operation has begun.
- ' 30 seconds later, and then every 30 seconds, the script checks the heatbeat of the vm.
- ' As soon as the vm produces heartbeat, the script starts to create
- ' a compressed archive from a previously copied vm directory.
- ' At that point of time is the vm already up and running.
- ' After the .zip file is ready, the script checks if there were any errors produced by 7zip.
- ' If there are some, the Windows Application log is misused for the registration of them.
- ' If not, then we can safely delete the copy of the vm used as a source for compression
- ' and create the record of successful backup operation in the Application log.
- ' The interactive mode (if you start the script without any parameters) does the same.
- ' You can manually name your zip file.
- ' The user who runs the script must have the write permissions on directory / network share.
- ' In the variable seven_zip_switch you can provide the additional switches for the command line of 7zip.
- ' The most thinkfully switch is " -v4g" (don't forget the leading space!). It causes the splitting of your
- ' archive into volumes at 4 GB. Please read the 7zip's manual about the -v switch.
- ' Please adapt the following five variables to your needs and go ahead!
- bkpath = "E:\backup\tmp\" 'Don't forget the ending slash!
- seven_zip_switch = ""
- adminmail = "admin@domain.tld" 'Here you'll receive mail messages.
- mailfrom = "vs-backup@domain.tld" 'The sender of mail messages. The address must be accepted by your SMTP server.
- smtp = "mx.domain.tld" 'SMTP server.
- 'Please do not edit anything after it...
- '---------------------------------------
- On Error Resume Next
- header = "Backup Script for Microsoft Virtual Server"
- Set wshShell = CreateObject("WScript.Shell")
- Set fso = CreateObject("Scripting.FileSystemObject")
- Set mailing = CreateObject("CDO.Message")
- mailing.From = mailfrom
- mailing.To = adminmail
- mailing.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
- mailing.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = smtp
- mailing.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
- Set vs = CreateObject("VirtualServer.Application")
- 'Check if the Virtual Server Application installed
- If Err.number <> 0 then
- errNoVS = header & " couldn't find the Virtual Server Application installed on your system."
- errNoVS = errNoVS & VbCrLf & "You can run this script only on a Microsoft Virtual Server host."
- wshShell.LogEvent 1, errNoVS
- mailing.Subject = header & ": Application not found."
- mailing.TextBody = errNoVS
- mailing.Configuration.Fields.Update
- mailing.Send
- If args.Count=0 Then
- cryVS = msgBox(errNoVS,vbCritical,header)
- End If
- WScript.Quit
- end if
- Err.Clear
- Set vm_collection = vs.VirtualMachines
- Function iso_date(byval dt)
- 'Creates an ISO date string like YYYY-MM-DD-HHMMSS
- dim y: y=year(dt)
- dim m: m=month(dt)
- dim d: d=day(dt)
- dim h: h=hour(dt)
- dim n: n=minute(dt)
- dim s: s=second(dt)
- if m < 10 then m="0" & m
- if d < 10 then d="0" & d
- if h < 10 then h="0" & h
- if n < 10 then n="0" & m
- if s < 10 then s="0" & s
- iso_date = y & "-" & m & "-" & d & "-" & h & n & s
- end Function
- 'Check if 7zip is installed
- seven_zip_reg = wshShell.RegRead("HKLM\SOFTWARE\7-Zip\Path")
- If Err.number <> 0 then
- errNoSevenZip = header & " couldn't find the 7-zip Application installed on your system."
- errNoSevenZip = errNoSevenZip & VbCrLf & "Please visit 7zip.org to get it."
- wshShell.LogEvent 1, errNoSevenZip
- mailing.Subject = header & ": Install 7-zip"
- mailing.TextBody = errNoSevenZip
- mailing.Configuration.Fields.Update
- mailing.Send
- If args.Count=0 Then
- crySevenZip = msgBox(errNoSevenZip,vbCritical,header)
- End If
- WScript.Quit
- end if
- Err.Clear
- 'Check and parse arguments
- Set args = WScript.Arguments
- If args.Count=1 Then
- 'We are in the mode with predefined vm by parameter, way = "a(utomatic)"
- vm_name = args(0)
- zipfile = bkpath & vm_name & "-" & iso_date(now) & ".zip"
- way = "a"
- ElseIf args.Count=0 Then
- 'We are in the interactive mode, way = "i(nteractive)"
- 'Initialize the VM list and show it.
- vmlist = ""
- For Each vm_member in vm_collection
- vmlist = vmlist & vm_member.Name & VbCrLf
- Next
- pe = "Please enter the name of the virtual machine "
- pe = pe & "you want to backup." & VbCrLf & VbCrLf
- pe = pe & "The list of the registered virtual machines follows." & VbCrLf
- pe = pe & VbCrLf & vmlist
- vm_name = inputBox(pe,header,"Please enter the VM name...")
- 'Quit if cancel
- if vm_name = "" then
- WScript.Quit
- end if
- bkfile = bkpath & vm_name & "-" & iso_date(now) & ".zip"
- 'Initialize "Save As..." dialog and show it
- Set file_save = CreateObject("SAFRCFileDlg.FileSave")
- file_save.FileName = vm_name & "-" & iso_date(now) & ".zip"
- file_save.FileType = ".zip Archive"
- file_selected = file_save.OpenFileSaveDlg
- If file_selected Then
- 'Why does it have to be so comlicated?!? :))))))
- Set new_file = fso.CreateTextFile(file_save.FileName)
- new_file.WriteLine "*"
- new_file.Close
- Set kill_file = fso.GetFile(file_save.FileName)
- kill_file.Delete
- 'Now it's worked out.
- zipfile = file_save.FileName
- Else
- Wscript.Quit
- End If
- way = "i"
- ElseIf args.Count=2 Then
- 'We are in the automatic mode with 2 Arguments: VM and backup location
- vm_name = args(0)
- zipfile = args(1)
- way = "a"
- Else
- 'There are more than two arguments provided: write the error message
- 'into the application log and bye.
- 'There is no message box / email here.
- errNoVMfile = header & ": Incorrect execution." & VbCrLf & "The name of the Virtual Machine "
- errNoVMfile = errNoVMfile & "must be provided as argument." & VbCrLf & VbCrLf
- errNoVMfile = errNoVMfile & "If the name contains spaces, "
- errNoVMfile = errNoVMfile & "please add the " & Chr(34) & " sign at the beginning "
- errNoVMfile = errNoVMfile & "and at the end of the Virtual Machine's name." & VbCrLf
- errNoVMfile = errNoVMfile & "The reading of the source code of the script may help ;)"
- wshShell.LogEvent 1, errNoVMfile
- WScript.Quit
- End If
- Set vm_object = vs.FindVirtualMachine(vm_name)
- vmfile = vm_object.File
- 'Check if the VM exists
- If vmfile = "" then
- errNoVM = header & " couldn't find the VM called " & Chr(34) & vm_name & Chr(34) & "."
- errNoVM = errNoVM & VbCrLf & "Please check if the VM is registered on the server."
- wshShell.LogEvent 1, errNoVM
- mailing.Subject = header & ": Incorrect Virtual Machine"
- mailing.TextBody = errNoVM
- mailing.Configuration.Fields.Update
- mailing.Send
- If way = "i" Then
- cryNoVM = msgBox(errNoVM,vbCritical,header)
- End If
- WScript.Quit
- end if
- vmfolder = fso.GetParentFolderName(vmfile)
- tmpfolder = fso.GetParentFolderName(zipfile) & "\" & vm_name
- 'Create the checkpoint: operation begin
- checkpoint_begin = now
- ps = vm_object.State
- if ps = 5 then 'running
- was_on = true 'It must be powered on after backup
- elseIf ps = 1 then 'turned off
- was_on = false 'After backup do nothing
- else 'If vm stucks, suspended or in unknown state... Who needs such backups?
- errState = header & " couldn't get the correct state of the virtual machine "
- errState = errState & vm_name & "." & VbCrLf & "Correct states are on and off only."
- wshShell.LogEvent 1, errState
- mailing.Subject = header & ": Critical Error"
- mailing.TextBody = errState
- mailing.Configuration.Fields.Update
- mailing.Send
- if way = "i" Then
- cryState = msgBox(errState,vbCritical,header)
- end if
- WScript.Quit
- end If
- 'Get a heartbeat of the guest OS
- Set os_object = vm_object.GuestOS
- hb = os_object.IsHeartbeating
- if was_on = true then
- if hb = False then 'VM Additions not installed or cannnot be contacted...
- 'VM without Additions can only be backed up if it was off...
- errAdd = header & " couldn't contact the Virtual Machine Additions on the virtual machine " & vm_name & "."
- errAdd = errAdd & VbCrLf & "Therefore it cannot be shut down correctly." & VbCrLf & "Please shut down the VM manually. "
- errAdd = errAdd & "Afterwards it can be backed up."
- wshShell.LogEvent 1, errAdd
- mailing.Subject = header & ": Critical Error"
- mailing.TextBody = errAdd
- mailing.Configuration.Fields.Update
- mailing.Send
- if way = "i" Then
- cryAdd = msgBox(errAdd,vbCritical,header)
- end if
- WScript.Quit
- end if
- end if
- 'Now stopping...
- getoff = os_object.Shutdown()
- WScript.Sleep 60 * 1000
- isoff = False
- For tries_off = 1 To 30
- ps_off = vm_object.State
- If ps_off = 1 Then
- isoff = True
- Exit For
- End If
- WScript.Sleep 30 * 1000
- ps_off = 5
- Next
- If Not isoff Then
- 'The vm couldn't be shut down: very critical...
- errNoShutDown = header & " couldn't shut down the virtual machine " & vm_name
- errNoShutDown = errNoShutDown & " in a reasonable time." & VbCrLf & "Please check it's state."
- wshShell.LogEvent 1, errNoShutDown
- mailing.Subject = header & ": Critical Error"
- mailing.TextBody = errNoShutDown
- mailing.Configuration.Fields.Update
- mailing.Send
- if way = "i" Then
- cryNoShutDown = msgBox(errNoShutDown,vbCritical,header)
- end if
- WScript.Quit
- end if
- 'Machine is shut down and can be copied
- copyVM = fso.CopyFolder(vmfolder,tmpfolder) 'checked
- 'Machine copied!
- if was_on = true then 'Power on the vm if it was on
- geton = vm_object.Startup()
- 'Wait for the heartbeat...
- ison = False
- For tries_on = 1 To 20
- hbs = os_object.IsHeartbeating
- If hbs = True Then
- ison = True
- Exit For
- End If
- WScript.Sleep 30 * 1000
- hbs = False
- Next
- If Not ison Then
- 'The vm couldn't be start up: very critical...
- errNoStart = header & " couldn't power on the virtual machine " & vm_name & " in a reasonable time. "
- errNoStart = errNoStart & "Maybe the machine could not start the Virtual Machine Additions." & VbCrLf
- errNoStart = errNoStart & "Please check it's state and / oder configuration."
- wshShell.LogEvent 1, errNoStart
- mailing.Subject = header & ": Critical Error"
- mailing.TextBody = errNoStart
- mailing.Configuration.Fields.Update
- mailing.Send
- if way = "i" Then
- cryNoStart = msgBox(errNoStart,vbCritical,header)
- end if
- WScript.Quit
- end if
- end if
- 'Now the vm is up and running. It is copied and ready to be compressed.
- 'Create the checkpoint: the VM is running.
- checkpoint_started = now
- WScript.Sleep 120 * 1000
- backup_string = chr(34) & seven_zip_reg & "\7z.exe" & chr(34) & " a -tzip "
- backup_string = backup_string & chr(34) & zipfile & chr(34) & " " & chr(34)
- backup_string = backup_string & tmpfolder & "\*" & chr(34) & seven_zip_switch
- 'Now create the archive...
- backup_vm = wshshell.Run(backup_string,0,true)
- if backup_vm > 0 then
- 'The zip file wasn't created
- errNozip = header & " couldn't create a zip file." & VbCrLf
- errNozip = errNozip & "Please check if you have enough disk space on "
- errNozip = errNozip & tmpfolder & " and run / schedule the backup script again."
- wshShell.LogEvent 1, errNozip
- mailing.Subject = header & ": Critical Error"
- mailing.TextBody = errNozip
- mailing.Configuration.Fields.Update
- mailing.Send
- if way = "i" Then
- cryNoZip = msgBox(errNozip,vbCritical,header)
- end if
- WScript.Quit
- end if
- 'Now delete the temporary backup folder...
- deltmp = fso.deleteFolder(tmpfolder) 'should be ok
- 'Pause...
- WScript.Sleep 5 * 1000
- 'Create the checkpoint: ready...
- checkpoint_ready = now
- ' Calculate time used...
- time_off = DateDiff("n",checkpoint_begin,checkpoint_started)
- time_cmp = DateDiff("n",checkpoint_started,checkpoint_ready)
- time_sum = time_off + time_cmp
- 'Estimate backup size.
- Set myfile = fso.GetFile(zipfile)
- filesize = Round ( (myfile.Size / 1024 / 1024 / 1024), 2 ) & " GB"
- success_message = header & " backed up the virtual machine " & vm_name
- success_message = success_message & " successfully." & VbCrLf
- success_message = success_message & "Backup is saved as " & zipfile & "; file size is "
- success_message = success_message & filesize & "."
- If was_on = true then
- success_message = success_message & VbCrLf & VbCrLf & "The VM was "
- success_message = success_message & time_off & " minutes offline."
- End If
- success_message = success_message & VbCrLf & VbCrLf & "The compress operation took "
- success_message = success_message & time_cmp & " minutes."
- success_message = success_message & VbCrLf & VbCrLf & "Total execution time was "
- success_message = success_message & time_sum & " minutes."
- success_message = success_message & VbCrLf & VbCrLf & "Operation begin was "
- success_message = success_message & iso_date(checkpoint_begin) & "."
- success_message = success_message & VbCrLf & VbCrLf & "Operation end was "
- success_message = success_message & iso_date(checkpoint_ready) & "."
- wshShell.LogEvent 0, success_message
- mailing.Subject = header & ": Backup Operation Successfully Completed"
- mailing.TextBody = success_message
- mailing.Configuration.Fields.Update
- mailing.Send
- if way = "i" Then
- cryS = msgBox(success_message,vbExclamation,header)
- end if
- WScript.Quit
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement