Since Vizioncore came out with vRanger 4.x, last year, I been working on porting the VBS script “vRanger Script version 2.0” to Powershell.
During this time I have found several bugs/missing functionality in the vAPI.
Vizioncore have corrected the bugs with new releases of vRanger.
The first vRanger version where all vAPI cmdlets worked in was version 4.2.3.
Porting the script from VBS presented me with a few challenges.
- A reported error in the Get-Date cmdlet in Powershel 2.0.
Had to use a workaround.
A few words on the scrips functionality.
- Control vRanger backups from vCenter (simple – one interface).
- Perform a FULL backup of DiskO of a VM.
- Perform a FULL backup of all disks of a VM.
- Backup a VM on a specific weekday.
- Control what week (Even/Odd).
- Create a log file.
- Delete previous backup files from repository.
- Delete previous savepoints.
- Send an email when the jobs are completed – incl. succes/errors.
- Offload the files to tape – TSM
- Send mail when TSM is finished offloading backup files.
- And many more…..
When I started coding the script, I found, that if I used functions for all functionality the script was easier to read. Using functions also supplied me with the opportunity of reusing functions – less work :-).
Some of the functions was created using examples posted and mailed by Scott Harold from Quest and TheVesi./vEcoShell.
Prerequirements
- Powershell 1.0 or 2.0 form Microsoft.
- Vizioncore vRanger 4.x
- A VMware vCenter server, a host and a few VMs.
The script can be downloaded here.
A quick overview of the functions.
Include the right PSSnapins
function LoadSnapin{ Add-PSSnapin vRanger.API.PowerShell -ErrorAction SilentlyContinue Add-PSSnapin vmware.VimAutomation.core -ErrorAction SilentlyContinue } LoadSnapin
Delete all previous savepoints – from the repository.
function RemoveAllSavePoints{ param ($RASP_RepoName) $RASP_repoID = Get-Repository | where {$_.Name -eq $RASP_RepoName} $RASP_SPlist = Get-RepositorySavePoint -ID $RASP_repoID.Id foreach ($RASP_SP in $RASP_SPlist){ #write $RASP_SP Remove-SavePoint -SavePointsToRemove $RASP_SP } } RemoveAllSavePoints "Remote-Location"
Is a backup job exist with the same name as the one to create – delete it.
function Del-vRangerBackupJobs { param ($delJobName) $delTemplateID = Get-JobTemplate | where {$_.JobName -eq $delJobName} # Verify that a BackupJob named XXX is present before deleting it. if ($delTemplateID){ #write $delTemplateID.JobName Remove-JobTemplate -id $delTemplateID.Id } } Del-vRangerBackupJobs "$Wednesday-Even"
Create the list of VMs to exclude.
function Filter-VMbyCF { param ($customF, $val) foreach ($vm in $vmlist) { $vm.CustomFields | ForEach-Object { $cf = $_ if ($_.Key -like $customF -and $_.Value -like $val){ return $vm.name } } } } function New-vRangerExcludeList { param ($exclude, $include) $excludeArray = @() $exclude | ForEach-Object { if ($include -notcontains $_.Name){ $excludeArray += ($_.Config.Uuid) } } return $excludeArray } $vmlist = Get-VM $tmplist = Get-Template $vmlist= $vmlist + $tmplist $vmFilter = Filter-VMbyCF $customField $CFValue $vmlistview = $vmlist | Get-View $excludeList = New-vRangerExcludeList -exclude $vmlistview -include $vmFilter
Create the new backup job.
function New-vRangerBackupJob { param ($customJobName, $customCFValue, $customFieldName, $customRepoName, $customExcludeList, $customEmail) $jobDesc = "This backup job is created by Logica for use in DR. All VMs with a Custom Field labeled: $customFieldName with a value of: $customCFValue will be backed up" $jobEntity = Get-InventoryEntity -Type VirtualCenter $jobRepos = Get-Repository | where {$_.Name -eq $customRepoName} $jobFlag = New-BackupFlag -CheckDestinationFreeSpace:$true -UseCompression:$true -PerformNetworkBackupOnFailure:$true # Check if all disks or just disk 0 if ($customJobName -like "*-All*"){ #write "All - Disks" #Add-BackupJobTemplate -JobName $customJobName -JobDescription $jobDesc -JobEntity $jobEntity -ExcludedVMList $customExcludeList -NotificationList $email -TargetRepository $jobRepos -Flags $jobFlag -NumberOfSavePoints 1 -SpaceSavingTechnologyTypeFlag None Add-BackupJobTemplate -JobName $customJobName -JobDescription $jobDesc -JobEntity $jobEntity -ExcludedVMList $customExcludeList -NotificationList $customEmail -TargetRepository $jobRepos -Flags $jobFlag -NumberOfSavePoints 1 -SpaceSavingTechnologyTypeFlag None -SpaceSavingCountThreshold 6 -SpaceSavingPercentSizeThreshold 50 } else{ #write "Only Disk 0" #Add-BackupJobTemplate -JobName $customJobName -JobDescription $jobDesc -JobEntity $jobEntity -ExcludedVMList $customExcludeList -NotificationList $email -IncludedDiskList 0 -TargetRepository $jobRepos -Flags $jobFlag -NumberOfSavePoints 1 -SpaceSavingTechnologyTypeFlag None Add-BackupJobTemplate -JobName $customJobName -JobDescription $jobDesc -JobEntity $jobEntity -ExcludedVMList $customExcludeList -NotificationList $customEmail -IncludedDiskList 0 -TargetRepository $jobRepos -Flags $jobFlag -NumberOfSavePoints 1 -SpaceSavingTechnologyTypeFlag None -SpaceSavingCountThreshold 6 -SpaceSavingPercentSizeThreshold 50 } } New-vRangerBackupJob "Wednesday-Even" "Wednesday-Even" "Backup" "Remote-Location" $excludeList "to@email.com"
Start the backup job.
function Run-BackupJob{ param ($runJobName) $runTemplateID = Get-TemplateID $runJobName Run-JobsNow $runTemplateID } Run-BackupJob "Wednesday-Even"
Wait for the backup job to finish.
function Get-TemplateID{ param($tmpJobName) $arrTemplate = get-jobtemplate | where {$_.JobName -eq $tmpJobName} return $arrTemplate.ID } function WaitForJobToFinish{ param ($strWaitJob) $strCompleted = "NotStarted" Start-Sleep -Seconds 300 # 5 minutes $jobTemplates = get-JobTemplate | where {$_.JobName -eq $strWaitJob} foreach ($job in $jobTemplates){ do{ $tasksinfo = get-job |where {$_.ParentJobTemplateID -eq $job.TemplateVersionID} foreach ($task in $tasksinfo){ Start-Sleep -Seconds 300 # 5 minutes $strCompleted = $task.JobState # Make sure job is running - if not start it... if ($task.JobState -eq $NULL -or $task.JobState -eq "NotStarted"){ Run-BackupJob $strWaitJob Start-Sleep -Seconds 120 # 2 minutes } } } while ($strCompleted -notmatch "Completed") } } WaitForJobToFinish "Wednesday-Even"
Send TSM finished mail.
function FuncMail { #param($strTo, $strFrom, $strSubject, $strBody, $smtpServer) param($To, $From, $Subject, $Body, $smtpServer) $msg = new-object Net.Mail.MailMessage $smtp = new-object Net.Mail.SmtpClient($smtpServer) $msg.From = $From $msg.To.Add($To) $msg.Subject = $Subject $msg.IsBodyHtml = 1 $msg.Body = $Body $smtp.Send($msg) } FuncMail -To "to@email.com" -From "from@email.com" -Subject "vRanger Pro: TSM backup finished" -Body "Your Body" -smtpServer "your.mailserver.com"
hi anders – great scripts – i have one question though .. if connecting directly to a Host and not a VC the filter by custom fields does not work. What changes would need to be made to the filter-bycmvf function in order for it to pick a value out of the notes field instead ? I have been trying to get it working but without success
Hi Chris,
Try this one – I haven’t tested it (no access to a host in france :-)), but it should give you an idear of where to look.
01 function Filter-VMbyCF {
02 param ( $val)
03 foreach ($vm in $vmlist) {
04 if ($vm.description -like $val){
07 return $vm.name
09 }
10 }
11 }
Thanks Anders – worked very well. Is there a way of getting the script to restore the backed up vm’s to a datastore on a different host once the backups have completed ? i have tried this using the ‘add-restorejobtemplate’ cmdlet and setting the variables for targetds, targetnw, etc etc. I think the problem i am having is with the savepoint value. How can i get the backed up vm’s to automatically restore them selves to another host ? any pointers you can give would be very useful
I haven’t played with the restore part yet, but have you looked at vcommunity.vizioncore.com?
Else i’ll try to put a script together over summer.
hi there,
great work here,
would you be able to send me a script to create a backup though powershell,
add vms i want to backup and days
Hi William,
Thanks for the feedback.
If you look at the functions above you should be able to create a script to do what you want.
If I get time and my test envirroment gets back online I’ll see what i can do, but I won’t promise anything.
A. Mikkelsen
William,
If I get you right you want a script to do the same as the script (http://www.amikkelsen.com/?p=475) I created to integrade vRanger into vCenter but without the vCenter integration – is this true?
Hello,
interesting stuff here. I’m new to powershell and scripting and was wondering if it is possible to have a script execute a command on a different server with different credentials before it starts a backup and after its done with backup.
We want to set the database on the server we want to backup in hot backup mode and back to normal when backup is finished…
Hope to hear from you.
Thanks for the stuff already up here…
Hi,
Haven’t got it to work from PowerShell, but it’s possible from vRanger 🙂
Only for Microsoft VM’s
Try to create a new job i vRanger.
In the Options Selection choose “Enable guest quiescing” to use Microsoft VSS.
If you want to control the script to be run you can use VMware Tools to invoke a script on the database servers.
Try to look at this post (http://www.amikkelsen.com/?p=357) on how to invoke a scripts through VMware Tools, or use google to search for “invoke-VMScript”.
Hope this helps you.
A. Mikkelsen