Create a script that will automatically stagger periodic backup jobs so that they are less likely to occur at the same time by adding some randomization as to how often the backup job is supposed to run.
Blog Describing Script
Learn more about my script at https://www.jasonpearce.com/2015/03/12/ ... owershell/.
Brief Explanation
Use the Get-Random cmdlet with -Minimum and -Maximum parameters to modify these backup job parameters:
Code: Select all
$jobScheduleOptions = New-VBRJobScheduleOptions
$jobScheduleOptions.OptionsPeriodically.FullPeriod
$jobScheduleOptions.OptionsPeriodically.HourlyOffset
$jobScheduleOptions.RetryTimeout
$jobScheduleOptions.LatestRun
$jobScheduleOptions.NextRun
Problem
The script works well. All of the above objects receive semi-random values. Veeam even begins performing backups following my scripted NextRun schedule. Once the backup runs, Veeam then automatically modifies the next NextRun schedule, which I assume is LastRun + FullPeriod + rounded up to HourlyOffset. All good.
The problem occurs once the FullPeriod crosses over into the next day. When that happens, Veeam appears to incorrectly calculate the NextRun schedule and instead configures NextRun to occur on the HourlyOffset between midnight and 1 am (example below). This causes all of my previously randomized and staggered backup jobs to overlap and run between midnight and 1 am.
My Big Question
How do I correct this behaviour? How do I have my randomized periodic backup jobs always wait the entire FullPeriod before running again, even if the NextRun carries over into the following day?
Script: Randomizing Veeam Backups
Here's the actual script.
Code: Select all
# Randomize Veeam Backups, a Veeam PowerShell script (Version 2)
# This script will add randomness to Veeam backup jobs by configuring them to use different periodic backup intervals
# Run this on a Veeam Backup and Replication version 8 update 1 server
# You could even copy and paste it into Veeam Backup and Replication > Menu > PowerShell
# Written by Jason Pearce of www.jasonpearce.com in March 2015
# Use at your own risk, freely share, and comment on improvements
# BEGIN Random variables #####################
# RandomFullPeriod: Variable for Schedule > Run the job automatically > Periodically every XX minutes. Must be a value between 0 and 999.
# Key: 1-8 hours 1h=60min, 2h=120min, 3h=180min, 4h=240min, 5h=300min, 6h=360min, 7h=420min, 8h=480min
# Key: 9-16 hours 9h=540min, 10h=600min, 11h=660min, 12h=720min, 13h=780min, 14h=840min, 15h=900min, 16h=960min
$RandomFullPeriodMinimum = 540
$RandomFullPeriodMaximum = 960
# RandomHourlyOffset: Variable for Schedule > Run the job automatically > Periodically every > Schedule > Start time within an hour. Must be a value between 0 and 59.
$RandomHourlyOffsetMinimum = 0
$RandomHourlyOffsetMaximum = 59
# RandomRetryTimeout: Variable for Schedule > Automatic Retry > Wait before each retry attempt for. Must be a value between 0 and 59.
$RandomRetryTimeoutMinimum = 10
$RandomRetryTimeoutMaximum = 50
# END Random variables #######################
# BEGIN Other variables ######################
# BackupRetention: Variables for RetainDays (amount of restore points) and RetainCycles (amount of days for Deleted VMs retention period).
$RetainDays = 14
$RetainCycles = 14
# Get All, Some, or One backup jobs.
# You MUST uncomment and modify one of these lines to target one or more backup jobs.
# Only one line should begin with "$jobs =". These are just four helpful examples.
#By-All# $jobs = Get-VBRJob | Where-Object { $_.IsBackup -eq $true -and $_.IsScheduleEnabled -eq $true } | Sort Name
#By-PREFIX# $jobs = Get-VBRJob -Name "Test-*" | Where-Object { $_.IsBackup -eq $true -and $_.IsScheduleEnabled -eq $true } | Sort Name
#By-LIST# $jobs = Get-VBRJob -Name "Test-1","Test-2" | Where-Object { $_.IsBackup -eq $true -and $_.IsScheduleEnabled -eq $true } | Sort Name
#By-NAME# $jobs = Get-VBRJob -Name "Test-Job" | Where-Object { $_.IsBackup -eq $true -and $_.IsScheduleEnabled -eq $true } | Sort Name
# END Other variables ########################
# BEGIN foreach loop #########################
# Make the following changes to all backup jobs
foreach ($job in $jobs) {
# BEGIN Job Options ######################
# Read current job settings
$jobOptions = Get-VBRJobOptions -Job $job
# Set more Job Advanced Storage Options
$jobOptions.BackupStorageOptions.RetainCycles = $RetainCycles
$jobOptions.BackupStorageOptions.RetainDays = $RetainDays
# Apply these additional Backup Mode settings
$jobOptions = Set-VBRJobOptions -Job $job -Options $jobOptions
# END Job Options ########################
# BEGIN Job Schedule Options #############
# Create a new job schedule
$jobScheduleOptions = New-VBRJobScheduleOptions
# Enable Periodically Schedule
$jobScheduleOptions.OptionsPeriodically.Enabled = $true
# Configure Periodic Schedule in Minutes (0 = Hours, 1 = Minutes)
$jobScheduleOptions.OptionsPeriodically.Kind = 1
# Disable Other Schedules
$jobScheduleOptions.OptionsDaily.Enabled = $false
$jobScheduleOptions.OptionsMonthly.Enabled = $false
$jobScheduleOptions.OptionsContinuous.Enabled = $false
# Generate random number for FullPeriod (Minimum and Maximum variables are defined above)
$RandomFullPeriod = Get-Random -Minimum $RandomFullPeriodMinimum -Maximum $RandomFullPeriodMaximum
# Create a random FullPeriod offset
$jobScheduleOptions.OptionsPeriodically.FullPeriod = $RandomFullPeriod
# Generate random number for HourlyOffset (Minimum and Maximum variables are defined above)
$RandomHourlyOffset = Get-Random -Minimum $RandomHourlyOffsetMinimum -Maximum $RandomHourlyOffsetMaximum
# Create a random HourlyOffset
$jobScheduleOptions.OptionsPeriodically.HourlyOffset = $RandomHourlyOffset
# Generate random number for RetryTimeout (Minimum and Maximum variables are defined above)
$RandomRetryTimeout = Get-Random -Minimum $RandomRetryTimeoutMinimum -Maximum $RandomRetryTimeoutMaximum
# Create a random RetryTimeout
$jobScheduleOptions.RetryTimeout = $RandomRetryTimeout
# Do some math to randomly stagger LatestRun (past) and NextRun (future), while correctly calculating the FullPeriod difference
$RandomlyStagger = Get-Random -Minimum 1 -Maximum 9
$jobScheduleOptions.LatestRun = (Get-Date).AddMinutes(-([math]::Round($RandomFullPeriod * $RandomlyStagger * .1)))
$jobScheduleOptions.NextRun = (Get-Date).AddMinutes([math]::Round($RandomFullPeriod * (10 - $RandomlyStagger) * .1))
# Apply the new job schedule
Set-VBRJobScheduleOptions -Job $job -Options $jobScheduleOptions
# END Job Schedule Options ###############
# Report which jobs received these changes
Write-Host "Changed settings for" $job.Name
}
# END foreach loop ###########################
# END Randomize Veeam Backups script #########
I also wrote a small script to just report on the new randomized values.
Code: Select all
# BEGIN REPORT ###############################
# Optionally Report New Job Schedule Options #
# Safe to delete this report #################
# Get all enabled backup jobs.
$jobs = Get-VBRJob -Name "*" | Where-Object { $_.IsBackup -eq $true -and $_.IsScheduleEnabled -eq $true } | Sort Name
# BEGIN foreach loop #########################
foreach ($job in $jobs) {
# Report which jobs have what schedules
Write-Host "------------------------------------"
Write-Host "Job Schedule settings for" $job.Name
# Get job schedule
$ReportJobScheduleOptions = Get-VBRJobScheduleOptions -Job $job
# Report on a few values
Write-Host "FullPer: " $ReportJobScheduleOptions.OptionsPeriodically.FullPeriod
Write-Host "HourOff: " $ReportJobScheduleOptions.OptionsPeriodically.HourlyOffset
Write-Host "LateRun: " $ReportJobScheduleOptions.LatestRun
Write-Host "NextRun: " $ReportJobScheduleOptions.NextRun
Write-Host ""
}
# END foreach loop ###########################
# Write current date and time
Get-Date
# END REPORT #################################
Code: Select all
------------------------------------
Job Schedule settings for Job-1
FullPer: 838
HourOff: 41
LateRun: 3/18/2015 1:43:04 PM
NextRun: 03/19/2015 03:41:04
------------------------------------
Job Schedule settings for Job-2
FullPer: 700
HourOff: 44
LateRun: 3/18/2015 4:02:05 PM
NextRun: 03/19/2015 03:42:05
------------------------------------
Job Schedule settings for Job-3
FullPer: 796
HourOff: 24
LateRun: 3/18/2015 6:03:06 PM
NextRun: 03/19/2015 07:19:06
------------------------------------
Job Schedule settings for Job-4
FullPer: 665
HourOff: 53
LateRun: 3/18/2015 12:56:07 PM
NextRun: 03/19/2015 00:02:07
------------------------------------
Job Schedule settings for Job-5
FullPer: 860
HourOff: 48
LateRun: 3/18/2015 2:58:08 PM
NextRun: 03/19/2015 05:18:08
Here's an example of the randomized jobs being scheduled for midnight to 1 am even though the FullPeriod should have them run sometime later.
Code: Select all
------------------------------------
Job Schedule settings for Job-1
FullPer: 572
HourOff: 7
LateRun: 3/18/2015 7:11:10 PM
NextRun: 03/19/2015 00:07:00
------------------------------------
Job Schedule settings for Job-2
FullPer: 889
HourOff: 48
LateRun: 3/18/2015 3:37:14 PM
NextRun: 03/19/2015 00:48:00
------------------------------------
Job Schedule settings for Job-3
FullPer: 911
HourOff: 43
LateRun: 3/18/2015 3:54:12 PM
NextRun: 03/19/2015 00:43:00
------------------------------------
Job Schedule settings for Job-4
FullPer: 595
HourOff: 31
LateRun: 3/18/2015 8:21:16 PM
NextRun: 03/19/2015 00:31:00
------------------------------------
Job Schedule settings for Job-5
FullPer: 926
HourOff: 19
LateRun: 3/18/2015 3:45:20 PM
NextRun: 03/19/2015 00:19:00
Code: Select all
Job 1
NextRun: 03/19/2015 04:43:10 (rounded up to 05:07 thanks to HourlyOffset)
Job 2
NextRun: 03/19/2015 06:26:14 (rounded up to 07:48 thanks to HourlyOffset)
Job 3
NextRun: 03/19/2015 07:05:12 (rounded up to 07:43 thanks to HourlyOffset)
Job 4
NextRun: 03/19/2015 06:16:16 (rounded up to 06:31 thanks to HourlyOffset)
Job 5
NextRun: 03/19/2015 07:11:20 (rounded up to 08:19 thanks to HourlyOffset)
Thank you for your help.