Advertisement
Guest User

saxa

a guest
Nov 1st, 2007
433
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ' Copyleft saxa aka Alexander Kaufmann, 2007
  2.  
  3. ' Written just for fun; total Open Source.
  4. ' Use it at your own risk.
  5.  
  6. ' The script uses the VS API for the virtual machine operations.
  7.  
  8. ' The virtual machine *must* have the Additions installed, in order to perform the
  9. ' shutdown and heartbeat operations correctly.
  10. 'On Linx guests, we need at least the shutdown and heartbeat packages, but they wouldn't run without the kernel package...
  11.  
  12. ' DON'T APPLY THIS SCRIPT ON RUNNING VIRTUAL MACHINES WHICH DON'T HAVE THE ADDITIONS INSTALLED.
  13.  
  14. ' The script doesn't use the NTBackup utility. It will work on all supported hosts, be it 32 or 64 bit.
  15.  
  16. ' The script runs on the local host only; it cannot be used to connect to a remote Virtual Server.
  17. ' The script *can* backup to the network share, if you have the appropriate permissions to write on it.
  18.  
  19. ' For the backup jobs it uses the command line version of 7zip. Download the full install of 7zip: if your host is 32bit,
  20. ' you'll need the 32bit version; for 64bit hosts please install the 64bit one.
  21.  
  22. ' Install 7zip with defaults; the script will find it as it's needed.
  23.  
  24. '  We assume that all of your virtual machine files are located in the appropriate subdirectories
  25. ' of *one* directory; in other words, we need a flat structure.  Subfolders are OK.
  26.  
  27. ' There are 3 methods of running the script.
  28.  
  29. ' The first one - by double-clicking of it. You will be prompted for the name
  30. ' of the VM you want to backup and for the location of the .zip file.
  31. ' When the job is ready, you'll get the message.
  32.  
  33. ' The second one is like
  34. ' "vs-backup.vbs "My Virtual Machine"" (or "wscript.exe vs-backup.vbs "My Virtual Machine"" if used in a scheduled task)
  35. ' It will backup your VM to the default location defined in the 'bkpath' variable
  36. ' and save your backup file as "My Virtual Machine-YYYY-MM-DD-HHMMSS.zip"
  37. '
  38. 'The third one is like
  39. ' "vs-backup.vbs "My Virtual Machine"  "X:\Full\Path\To\My\Backup\File.zip""
  40. ' (or "wscript.exe vs-backup.vbs "My Virtual Machine" "X:\Full\Path\To\My\Backup\File.zip"" if used in a scheduled task)
  41. ' It will backup your VM to the file defined in the second parameter.
  42.  
  43. ' The script does the following:
  44.  
  45. ' The virtual machine receives the command to shut down it's operating system.
  46. ' The script waits 30 seconds and than checks the state of the virtual machine.
  47. ' If the vm still runs, the script waits 30 seconds more and so on.
  48. ' As soon as the vm is off, the script copies the vm's folder into the backup location.
  49.  
  50. ' If the vm couldn't be shut down, the mail is sent to the admin,
  51. ' the error is written in the Windows application log.
  52.  
  53. ' After the copying is done, the vm receives the command to start, if it was running before the operation has begun.
  54. ' 30 seconds later, and then every 30 seconds, the script checks the heatbeat of the vm.
  55. ' As soon as the vm produces heartbeat, the script starts to create
  56. ' a compressed archive from a previously copied vm directory.
  57. ' At that point of time is the vm already up and running.
  58. ' After the .zip file is ready, the script checks if there were any errors produced by 7zip.
  59. ' If there are some, the Windows Application log is misused for the registration of them.
  60. ' If not, then we can safely delete the copy of the vm used as a source for compression
  61. ' and create the record of successful backup operation in the Application log.
  62.  
  63. ' The interactive mode (if you start the script without any parameters) does the same.
  64. ' You can manually name your zip file.
  65.  
  66. ' The user who runs the script must have the write permissions on directory / network share.
  67.  
  68. ' In the variable seven_zip_switch you can provide the additional switches for the command line of 7zip.
  69. ' The most thinkfully switch is " -v4g" (don't forget the leading space!). It causes the splitting of your
  70. ' archive into volumes at 4 GB. Please read the 7zip's manual about the -v switch.
  71.  
  72. ' Please adapt the following five variables to your needs and go ahead!
  73.  
  74. bkpath = "E:\backup\tmp\"               'Don't forget the ending slash!
  75. seven_zip_switch = ""
  76. adminmail = "admin@domain.tld"          'Here you'll receive mail messages.
  77. mailfrom = "vs-backup@domain.tld"       'The sender of mail messages. The address must be accepted by your SMTP server.
  78. smtp = "mx.domain.tld"                  'SMTP server.
  79.  
  80. 'Please do not edit anything after it...
  81. '---------------------------------------
  82. On Error Resume Next
  83.  
  84. header = "Backup Script for Microsoft Virtual Server"
  85. Set wshShell = CreateObject("WScript.Shell")
  86. Set fso = CreateObject("Scripting.FileSystemObject")
  87. Set mailing = CreateObject("CDO.Message")
  88. mailing.From = mailfrom
  89. mailing.To = adminmail
  90. mailing.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
  91. mailing.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = smtp
  92. mailing.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
  93. Set vs = CreateObject("VirtualServer.Application")
  94. 'Check if the Virtual Server Application installed
  95. If Err.number <> 0 then
  96.     errNoVS = header & " couldn't find the Virtual Server Application installed on your system."
  97.     errNoVS = errNoVS & VbCrLf & "You can run this script only on a Microsoft Virtual Server host."
  98.     wshShell.LogEvent 1, errNoVS
  99.     mailing.Subject = header & ": Application not found."
  100.     mailing.TextBody = errNoVS
  101.     mailing.Configuration.Fields.Update
  102.     mailing.Send
  103.     If args.Count=0 Then
  104.         cryVS = msgBox(errNoVS,vbCritical,header)
  105.     End If
  106.     WScript.Quit
  107. end if
  108. Err.Clear
  109.  
  110. Set vm_collection = vs.VirtualMachines
  111.  
  112. Function iso_date(byval dt)
  113. 'Creates an ISO date string like YYYY-MM-DD-HHMMSS
  114. dim y: y=year(dt)
  115. dim m: m=month(dt)
  116. dim d: d=day(dt)
  117. dim h: h=hour(dt)
  118. dim n: n=minute(dt)
  119. dim s: s=second(dt)
  120.  
  121. if m < 10 then m="0" & m
  122. if d < 10 then d="0" & d
  123. if h < 10 then h="0" & h
  124. if n < 10 then n="0" & m
  125. if s < 10 then s="0" & s
  126.  
  127. iso_date = y & "-" & m & "-" & d & "-" & h & n & s
  128.  
  129. end Function
  130.  
  131. 'Check if 7zip is installed
  132. seven_zip_reg = wshShell.RegRead("HKLM\SOFTWARE\7-Zip\Path")
  133. If Err.number <> 0 then
  134.     errNoSevenZip = header & " couldn't find the 7-zip Application installed on your system."
  135.     errNoSevenZip = errNoSevenZip & VbCrLf & "Please visit 7zip.org to get it."
  136.     wshShell.LogEvent 1, errNoSevenZip
  137.     mailing.Subject = header & ": Install 7-zip"
  138.     mailing.TextBody = errNoSevenZip
  139.     mailing.Configuration.Fields.Update
  140.     mailing.Send
  141.     If args.Count=0 Then
  142.         crySevenZip = msgBox(errNoSevenZip,vbCritical,header)
  143.     End If
  144.     WScript.Quit
  145. end if
  146. Err.Clear
  147. 'Check and parse arguments
  148. Set args = WScript.Arguments
  149.  
  150. If args.Count=1 Then
  151. 'We are in the mode with predefined vm by parameter, way = "a(utomatic)"
  152.     vm_name = args(0)
  153.     zipfile = bkpath & vm_name & "-" & iso_date(now) & ".zip"
  154.     way = "a"
  155. ElseIf args.Count=0 Then
  156.     'We are in the interactive mode, way = "i(nteractive)"
  157.     'Initialize the VM list and show it.
  158.     vmlist = ""
  159.     For Each vm_member in vm_collection
  160.         vmlist = vmlist & vm_member.Name & VbCrLf
  161.     Next
  162.     pe = "Please enter the name of the virtual machine "
  163.     pe = pe & "you want to backup." & VbCrLf & VbCrLf
  164.     pe = pe & "The list of the registered virtual machines follows." & VbCrLf
  165.     pe = pe  & VbCrLf & vmlist
  166.     vm_name = inputBox(pe,header,"Please enter the VM name...")
  167.     'Quit if cancel
  168.     if vm_name = "" then
  169.         WScript.Quit
  170.     end if
  171.    
  172.     bkfile = bkpath & vm_name & "-" & iso_date(now) & ".zip"
  173.    
  174.     'Initialize "Save As..." dialog and show it
  175.     Set file_save = CreateObject("SAFRCFileDlg.FileSave")
  176.     file_save.FileName = vm_name & "-" & iso_date(now) & ".zip"
  177.     file_save.FileType = ".zip Archive"
  178.     file_selected = file_save.OpenFileSaveDlg
  179.     If file_selected Then
  180.         'Why does it have to be so comlicated?!? :))))))
  181.         Set new_file = fso.CreateTextFile(file_save.FileName)
  182.         new_file.WriteLine "*"
  183.         new_file.Close
  184.         Set kill_file = fso.GetFile(file_save.FileName)
  185.         kill_file.Delete
  186.         'Now it's worked out.
  187.    zipfile = file_save.FileName
  188.     Else
  189.         Wscript.Quit
  190.     End If
  191.     way = "i"
  192.    
  193.     ElseIf args.Count=2 Then
  194.    
  195.     'We are in the automatic mode with 2 Arguments: VM and backup location
  196.     vm_name = args(0)
  197.     zipfile = args(1)
  198.     way = "a"
  199. Else
  200.    
  201. 'There are more than two arguments provided: write the error message
  202. 'into the application log and bye.
  203. 'There is no message box / email here.
  204.  
  205. errNoVMfile = header & ": Incorrect execution." & VbCrLf & "The name of the Virtual Machine "
  206. errNoVMfile = errNoVMfile & "must be provided as argument." & VbCrLf & VbCrLf
  207. errNoVMfile = errNoVMfile & "If the name contains spaces, "
  208. errNoVMfile = errNoVMfile & "please add the " & Chr(34) & " sign at the beginning "
  209. errNoVMfile = errNoVMfile & "and at the end of the Virtual Machine's name." & VbCrLf
  210. errNoVMfile = errNoVMfile & "The reading of the source code of the script may help ;)"
  211.  
  212. wshShell.LogEvent 1, errNoVMfile
  213. WScript.Quit
  214. End If
  215.  
  216. Set vm_object = vs.FindVirtualMachine(vm_name)
  217. vmfile = vm_object.File
  218. 'Check if the VM exists
  219. If vmfile = "" then
  220.     errNoVM = header & " couldn't find the VM called " & Chr(34) & vm_name & Chr(34) & "."
  221.     errNoVM = errNoVM & VbCrLf & "Please check if the VM is registered on the server."
  222.     wshShell.LogEvent 1, errNoVM
  223.     mailing.Subject = header & ": Incorrect Virtual Machine"
  224.     mailing.TextBody = errNoVM
  225.     mailing.Configuration.Fields.Update
  226.     mailing.Send
  227.     If way = "i" Then
  228.         cryNoVM = msgBox(errNoVM,vbCritical,header)
  229.     End If
  230.     WScript.Quit
  231. end if
  232.  
  233. vmfolder = fso.GetParentFolderName(vmfile)
  234. tmpfolder = fso.GetParentFolderName(zipfile) & "\" & vm_name
  235.  
  236. 'Create the checkpoint: operation begin
  237. checkpoint_begin = now
  238.  
  239. ps = vm_object.State
  240.  
  241. if ps = 5 then 'running
  242.     was_on = true   'It must be powered on after backup
  243. elseIf ps = 1 then 'turned off
  244.     was_on = false  'After backup do nothing
  245. else 'If vm stucks, suspended or in unknown state... Who needs such backups?
  246.     errState = header & " couldn't get the correct state of the virtual machine "
  247.     errState = errState & vm_name & "." & VbCrLf & "Correct states are on and off only."   
  248.     wshShell.LogEvent 1, errState
  249.     mailing.Subject = header & ": Critical Error"
  250.     mailing.TextBody = errState
  251.     mailing.Configuration.Fields.Update
  252.     mailing.Send
  253.     if way = "i" Then
  254.         cryState = msgBox(errState,vbCritical,header)
  255.     end if
  256.     WScript.Quit
  257. end If
  258.  
  259. 'Get a heartbeat of the guest OS
  260.  
  261. Set os_object = vm_object.GuestOS
  262. hb = os_object.IsHeartbeating
  263.  
  264. if was_on = true then
  265.     if hb = False then  'VM Additions not installed or cannnot be contacted...
  266.     'VM without Additions can only be backed up if it was off...
  267.     errAdd = header & " couldn't contact the Virtual Machine Additions on the virtual machine " & vm_name & "."
  268.     errAdd = errAdd & VbCrLf & "Therefore it cannot be shut down correctly." & VbCrLf & "Please shut down the VM manually. "
  269.     errAdd = errAdd & "Afterwards it can be backed up."
  270.     wshShell.LogEvent 1, errAdd
  271.     mailing.Subject = header & ": Critical Error"
  272.     mailing.TextBody = errAdd
  273.     mailing.Configuration.Fields.Update
  274.     mailing.Send
  275.     if way = "i" Then
  276.         cryAdd = msgBox(errAdd,vbCritical,header)
  277.     end if
  278.     WScript.Quit
  279.     end if
  280. end if
  281.  
  282. 'Now stopping...
  283.  
  284. getoff = os_object.Shutdown()
  285. WScript.Sleep 60 * 1000
  286. isoff = False
  287. For tries_off = 1 To 30
  288.         ps_off = vm_object.State
  289.         If ps_off = 1 Then
  290.         isoff = True
  291.         Exit For
  292.         End If
  293.     WScript.Sleep 30 * 1000
  294.     ps_off = 5
  295.    
  296. Next
  297.  
  298. If Not isoff Then
  299.     'The vm couldn't be shut down: very critical...
  300.     errNoShutDown = header & " couldn't shut down the virtual machine " & vm_name
  301.     errNoShutDown = errNoShutDown & " in a reasonable time." & VbCrLf & "Please check it's state."
  302.     wshShell.LogEvent 1, errNoShutDown
  303.     mailing.Subject = header & ": Critical Error"
  304.     mailing.TextBody = errNoShutDown
  305.     mailing.Configuration.Fields.Update
  306.     mailing.Send
  307.     if way = "i" Then
  308.         cryNoShutDown = msgBox(errNoShutDown,vbCritical,header)
  309.     end if
  310.     WScript.Quit
  311. end if
  312.  
  313. 'Machine is shut down and can be copied
  314. copyVM = fso.CopyFolder(vmfolder,tmpfolder) 'checked
  315. 'Machine copied!
  316.  
  317. if was_on = true then   'Power on the vm if it was on
  318.     geton = vm_object.Startup()
  319.     'Wait for the heartbeat...
  320.     ison = False
  321.     For tries_on = 1 To 20
  322.         hbs = os_object.IsHeartbeating
  323.         If hbs = True Then
  324.         ison = True
  325.         Exit For
  326.         End If
  327.     WScript.Sleep 30 * 1000
  328.     hbs = False
  329.     Next
  330.  
  331.     If Not ison Then
  332.     'The vm couldn't be start up: very critical...
  333.     errNoStart = header & " couldn't power on the virtual machine " & vm_name & " in a reasonable time. "
  334.     errNoStart = errNoStart & "Maybe the machine could not start the Virtual Machine Additions." & VbCrLf
  335.     errNoStart = errNoStart & "Please check it's state and / oder configuration."
  336.     wshShell.LogEvent 1, errNoStart
  337.     mailing.Subject = header & ": Critical Error"
  338.     mailing.TextBody = errNoStart
  339.     mailing.Configuration.Fields.Update
  340.     mailing.Send
  341.     if way = "i" Then
  342.         cryNoStart = msgBox(errNoStart,vbCritical,header)
  343.     end if
  344.     WScript.Quit
  345.     end if
  346.    
  347. end if
  348.  
  349. 'Now the vm is up and running. It is copied and ready to be compressed.
  350. 'Create the checkpoint: the VM is running.
  351. checkpoint_started = now
  352.  
  353. WScript.Sleep 120 * 1000
  354.  
  355. backup_string = chr(34) & seven_zip_reg & "\7z.exe" & chr(34) & " a -tzip "
  356. backup_string = backup_string & chr(34) & zipfile & chr(34) & " " & chr(34)
  357. backup_string = backup_string & tmpfolder & "\*" & chr(34) & seven_zip_switch
  358. 'Now create the archive...
  359. backup_vm = wshshell.Run(backup_string,0,true)
  360. if backup_vm > 0 then
  361. 'The zip file wasn't created
  362.     errNozip = header & " couldn't create a zip file." & VbCrLf
  363.     errNozip = errNozip & "Please check if you have enough disk space on "
  364.     errNozip = errNozip & tmpfolder & " and run / schedule the backup script again."
  365.     wshShell.LogEvent 1, errNozip
  366.     mailing.Subject = header & ": Critical Error"
  367.     mailing.TextBody = errNozip
  368.     mailing.Configuration.Fields.Update
  369.     mailing.Send
  370.         if way = "i" Then
  371.         cryNoZip = msgBox(errNozip,vbCritical,header)
  372.     end if
  373.     WScript.Quit
  374. end if
  375.  
  376. 'Now delete the temporary backup folder...
  377. deltmp = fso.deleteFolder(tmpfolder)    'should be ok
  378. 'Pause...
  379. WScript.Sleep 5 * 1000
  380. 'Create the checkpoint: ready...
  381. checkpoint_ready = now
  382. '   Calculate time used...
  383. time_off =  DateDiff("n",checkpoint_begin,checkpoint_started)
  384. time_cmp = DateDiff("n",checkpoint_started,checkpoint_ready)
  385. time_sum = time_off + time_cmp
  386. 'Estimate backup size.
  387. Set myfile = fso.GetFile(zipfile)
  388. filesize = Round ( (myfile.Size / 1024 / 1024 / 1024), 2 ) & " GB"
  389. success_message = header & " backed up the virtual machine " & vm_name
  390. success_message = success_message & " successfully." & VbCrLf
  391. success_message = success_message & "Backup is saved as " & zipfile & "; file size is "
  392. success_message = success_message & filesize & "."
  393.  
  394. If was_on = true then
  395.     success_message = success_message & VbCrLf & VbCrLf & "The VM was "
  396.     success_message = success_message & time_off & " minutes offline."
  397. End If
  398.  
  399. success_message = success_message & VbCrLf & VbCrLf & "The compress operation took "
  400. success_message = success_message & time_cmp & " minutes."
  401. success_message = success_message & VbCrLf & VbCrLf & "Total execution time was "
  402. success_message = success_message & time_sum & " minutes."
  403. success_message = success_message & VbCrLf & VbCrLf & "Operation begin was "
  404. success_message = success_message & iso_date(checkpoint_begin) & "."
  405. success_message = success_message & VbCrLf & VbCrLf & "Operation end was "
  406. success_message = success_message & iso_date(checkpoint_ready) & "."
  407.    
  408. wshShell.LogEvent 0, success_message
  409. mailing.Subject = header & ": Backup Operation Successfully Completed"
  410. mailing.TextBody = success_message
  411. mailing.Configuration.Fields.Update
  412. mailing.Send
  413. if way = "i" Then
  414.     cryS = msgBox(success_message,vbExclamation,header)
  415. end if
  416. WScript.Quit
  417.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement