The Surly Admin

Father, husband, IT Pro, cancer survivor

Veeam Backups – Wait for Jobs to Finish

If you have Veeam Backup and Replication software, you know what a great backup program it is.  You also know it completely lacks any ability to copy its backup files to tape or external media–though Veeam is saying that with their next major release they will have this capability.  Until that happens we need to use another program to copy these files and to do the few things Veeam can’t do, I use Backup Exec for these tasks.  But one thing that’s lacking is any real tie between Backup Exec (BE) and Veeam.  What do I mean by that?  I schedule my weekly copy of Veeam backup files and hope that the Veeam backups are actually done before it runs.  This simple script takes the guess work out of it and puts you back in control.  Read on to see what I mean.

The Needs Be

The problem is I need my Backup Exec job, that copies the Veeam backup files to tape, to wait until all Veeam backup jobs have completed.  I also need to make sure that another Veeam backup doesn’t start while I’m copying files and cause a locked file.  This is easy enough with the Powershell snapin’s provided by Veeam, one script to wait and disable the backup jobs and then a second script to re-enable them.

But I didn’t want to have 2 different scripts, I just wanted one that could easily do both jobs.  It’s easier to document, easier to understand, etc.  I also decided I wanted to work on some more advanced parameters, specifically the ability to validate a parameter before moving forward with the script.

The Script

First things first, as always, let’s define our user defineable variables.

Param (
[Parameter(Mandatory=$true,
HelpMessage="RunType must be either Wait or Finish")]
[ValidatePattern("Wait|Finish")]
[string]$RunType,
[int]$WaitTime = 300
)

This is where we start using the advanced parameter settings.  One thing to keep in mind, these settings only apply to the parameter we’re working on.  That means while $RunType is set to be mandatory, $WaitTime is not.  I also put out a friendly little help message if you forget to run the script without specifying -RunType.  The last part is the ValidatePattern piece, which uses a Regular Expression to validate the text you put into RunType.  The pipe, in RegEx, means “or” so to successfully validate you must put in “Wait” or “Finish”.  It is not case sensitive, so “wait” or “finish” also works just fine.

I also give you the ability to change how long the script will wait in between checking Veeam for running backups.  I think 5 minutes is just fine, but maybe you want to check every minute so can change the wait time to 60.


Add-PSSnapin VeeamPSSnapin -ErrorAction SilentlyContinue
If ((Get-PSSnapin "*Veeam*" -ErrorAction SilentlyContinue) -eq $null)
{ Write-Verbose "Unable to load Veeam snapin, you must run this on your Veeam backup server, and the Powershell snapin must be installed.`n`n"
Return 999
}

By default, Veeam does not load their snapin into Powershell, nor do they provide you with a specialized shell with it preloaded (many programs do this like Exchange or VMware’s PowerCLI).  So we have to make sure it’s loaded.  The Add-PSSnapin cmdlet is what we use, and we specify VeeamPSSnapin as the module we want to load.  I use the -ErrorAction SilentlyContinue to suppress any error messages that migh come up (which will happen if the snapin is already loaded).  After that, I use Get-PSSnapin to check if any snapin’s are loaded with the word “Veeam” in them.  If there isn’t write out an error and exit the script.  I use the Return statement to exit the script with a 999 error code so that Backup Exec (or whatever program you use) can detect a bad run and deal with it.


If ($RunType -eq "Wait")
{ #Wait for running jobs to complete
$RunningJobs = $true
Do {
If (@(Get-VBRBackupSession | Where { $_.isCompleted -eq $false }).Count -gt 0)
{
Write-Verbose "."
Start-Sleep -Seconds $WaitTime
}
Else
{
$RunningJobs = $false
Get-VBRJob | ForEach {
$_.DisableScheduler()
}
Write-Verbose "All backup jobs have completed and have been disabled.`n`n"
}
}
While ($RunningJobs)
}

Now I check the RunType and if it’s set to “Wait” we’ll begin that process.  The first thing I need to do is set up my loop (as long as $RunningJobs is $true the loop will process).  Then I check Veeam to see if any jobs are currently running.  Since Get-VBRBackupSession returns a PSObject, I force the results into an array and use the .count property to check if anything is returned.  As long as that count is over 0 then we know there is a Veeam backup job running (technically a restore too) and we need to continue to wait.  When this value finally hits 0 the script will use Get-VBRJob to enumerate all defined backup jobs and use the DisableScheduler() method to disable the schedules, hence stopping any more jobs from running.  We can safely exit the loop at this point and the “Wait” mode processing is completed.


Else
{ #Reenable backup jobs
Get-VBRJob | ForEach {
$_.EnableScheduler()
}
Write-Verbose "All backup jobs have been re-enabled.`n`n"
}
Return 0

If $RunType is set to “Finish” then we need to re-enable all of the Veeam backups so things can go back to normal.  Again, you would use this parameter after you’ve finished copying the Veeam backup files to tape (or other media).  Pretty much the same code as the disable part above, just using the EnableScheduler() method instead.

At the very end, both modes will use the Return statement to exit the script with a 0 return code which indicates that the script ended successfully.

Closing Thoughts

I know earlier this week I said I had some other projects and this wasn’t in the list, it was something that occurred to me while I was recovering from the server crash and finally got backup running again.  It was month-end and I just didn’t have a clean backup to tape and needed to manually make sure my Veeam to Tape job ran properly when it occurred to me I need to take more control of this process.  It’s fine 90% of the time, but I wanted to stop worrying about the last 10% and hence this script was born.  Besides, it’s always more fun to work on something new!

Enjoy!
You can find the full source code here.

Advertisement

November 8, 2012 - Posted by | PowerShell | , ,

1 Comment »

  1. It works fine with EMC networker. I only had to add this line at the beginning when debugging to be able to see messages from the script:

    $VerbosePreference = “Continue”

    Thanks a lot.

    Comment by nacho martin. | January 14, 2013 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: