Standalone backup agent for Microsoft Windows servers and workstations (formerly Veeam Endpoint Backup FREE)
Post Reply
lukasholzknecht
Service Provider
Posts: 37
Liked: 5 times
Joined: Nov 03, 2016 10:56 am
Contact:

Veeam Agent for Windows - time based Throttling/Bandwith limit Policy

Post by lukasholzknecht » 1 person likes this post

Hi,
we recently had the case where some of our tenants had bandwith issues caused by still running backup jobs pointing to Cloudconnect/Objectstorage repositories during work hours. Veeam Agent for Windows just offers a general bandwith throttling option but no possibility to apply only during work hours. We realized the time based throttling policy through a registry key indicated by veeam support which is set according to predefined time windows through windows task scheduler. In case anyone finds it useful below the script and the XML which can be imported as scheduled Task.

-Script

Code: Select all

<#.SYNOPSIS
    Veeam Agent Bandwidth Throttling Scheduler (Registry-Based)
.DESCRIPTION
    Schedules and manages Veeam Agent bandwidth throttling via registry key:
    HKEY_LOCAL_MACHINE\SOFTWARE\Veeam\Veeam Endpoint Backup
    Dev_RepositoryThrottlingMb (REG_DWORD)
#>

# ====================== CONFIGURATION ====================
$Config = @{
    LogPath            = "C:\System\Veeambackup\VeeamBandwithScheduler\VeeamBandwidthScheduler.log"
    MaxLogSizeMB       = 10
    LogRetentionDays   = 30

    # Bandwidth limits in Mbps (script will convert to MB/s for registry)
    BusinessHoursLimit = 8   # Mbps for business hours
    OffHoursLimit      = 0    # 0 = No limit
    WeekendLimit       = 0    # 0 = No limit

    # Time Windows
    BusinessHours = @{
        StartHour = 7
        EndHour   = 18
        Days      = @('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday')
    }
    WeekendDays = @('Saturday', 'Sunday')

    # Registry Target
    RegistryPath = 'HKLM:\SOFTWARE\Veeam\Veeam Endpoint Backup'
    RegistryValueName = 'Dev_RepositoryThrottlingMb'
    BackupPath = "C:\System\Veeambackup\VeeamBandwithScheduler\VeeamRegistryBackup_$(Get-Date -Format yyyyMMddHHmmss).reg"

    # Logging
    EnableDetailedLogging = $true
}

# ========================= LOGGING =========================
function Write-Log {
    param([string]$Message, [string]$Level="INFO")
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $entry = "[$timestamp] [$Level] $Message"
    Add-Content -Path $Config.LogPath -Value $entry
    if ($Config.EnableDetailedLogging -or $Level -eq "ERROR") { Write-Host $entry }
}
function Manage-LogFiles {
    if (Test-Path $Config.LogPath) {
        $logFile = Get-Item $Config.LogPath
        if ($logFile.Length -gt ($Config.MaxLogSizeMB * 1MB)) {
            $archive = $Config.LogPath -replace "\.log$", "_$((Get-Date).ToString('yyyyMMddHHmmss')).log"
            Move-Item $Config.LogPath $archive
            Write-Log "Log rotated to $archive"
        }
        # Cleanup old logs
        $logDir = Split-Path $Config.LogPath
        Get-ChildItem $logDir -Filter "*.log" | Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-$Config.LogRetentionDays)} | ForEach-Object {Remove-Item $_.FullName}
    }
}
# ================== REGISTRY FUNCTIONS ====================
function Backup-VeeamRegSetting {
    Write-Log "Backing up registry to $($Config.BackupPath)"
    reg export "HKLM\SOFTWARE\Veeam\Veeam Endpoint Backup" $Config.BackupPath /y | Out-Null
}
function Get-VeeamThrottlingReg {
    try {
        $val = Get-ItemProperty -Path $Config.RegistryPath -Name $Config.RegistryValueName -ErrorAction Stop
        Write-Log "Current registry value: $($val.Dev_RepositoryThrottlingMb) MB/s" "DEBUG"
        return $val.Dev_RepositoryThrottlingMb
    } catch {
        Write-Log "Registry value not found, assuming throttling OFF" "WARN"
        return 0
    }
}
function Set-VeeamThrottlingReg {
    param([int]$MbPerSec)
    try {
        Write-Log "Updating Veeam throttling to $MbPerSec MB/s (REG_DWORD $($Config.RegistryPath) $($Config.RegistryValueName))"
        Set-ItemProperty -Path $Config.RegistryPath -Name $Config.RegistryValueName -Value $MbPerSec -Type DWord
        Write-Log "Registry updated successfully"
        return $true
    } catch {
        Write-Log "ERROR setting Veeam throttling in registry: $_" "ERROR"
        return $false
    }
}

# ================== SCHEDULING LOGIC ======================
function Get-CurrentTimeWindow {
    $now    = Get-Date
    $day    = $now.DayOfWeek.ToString()
    $hour   = $now.Hour

    if ($Config.WeekendDays -contains $day) {
        return @{ Window="Weekend"; BandwidthMbps=$Config.WeekendLimit }
    }
    if ($Config.BusinessHours.Days -contains $day -and $hour -ge $Config.BusinessHours.StartHour -and $hour -lt $Config.BusinessHours.EndHour) {
        return @{ Window="BusinessHours"; BandwidthMbps=$Config.BusinessHoursLimit }
    }
    return @{ Window="OffHours"; BandwidthMbps=$Config.OffHoursLimit }
}

function MbpsToMBps([int]$Mbps) {
    [int][Math]::Round($Mbps / 8)
}

function Invoke-BandwidthScheduling {
    Write-Log "Checking current schedule/time window"
    $win = Get-CurrentTimeWindow
    $throttleMb = if ($win.BandwidthMbps -le 0) {0} else {MbpsToMBps $win.BandwidthMbps}
    Write-Log "Throttling to $($win.BandwidthMbps) Mbps ($throttleMb MB/s) for window $($win.Window)"
    $curr = Get-VeeamThrottlingReg
    if ($curr -ne $throttleMb) {
        Backup-VeeamRegSetting
        Set-VeeamThrottlingReg $throttleMb | Out-Null
    } else {
        Write-Log "No registry update needed, value already correct"
    }
    return $true
}
# ================== SCRIPT ENTRY ==================
param(
    [ValidateSet("Schedule", "Test", "Status", "Help")]
    [string]$Operation = "Schedule"
)

if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")) {
    Write-Error "Script must be run as Administrator"
    exit 1
}
Manage-LogFiles

switch ($Operation) {
    "Schedule" {
        Invoke-BandwidthScheduling
        exit 0
    }
    "Test" {
        Write-Log "Testing registry setting and logic:"
        $curr = Get-VeeamThrottlingReg
        Write-Host "Current registry bandwidth: $curr MB/s"
        $win = Get-CurrentTimeWindow
        Write-Host "Time window: $($win.Window), Limit: $($win.BandwidthMbps) Mbps"
        Write-Host "Would set registry to: $(if($win.BandwidthMbps -le 0){0}else{MbpsToMBps $win.BandwidthMbps}) MB/s"
    }
    "Status" {
        $curr = Get-VeeamThrottlingReg
        Write-Host "Current Veeam registry throttle: $curr MB/s"
    }
    "Help" {
        Write-Host @"
This script will update the Veeam bandwidth throttling setting for Windows Agent using the registry key:
   HKLM:\SOFTWARE\Veeam\Veeam Endpoint Backup
   Value: Dev_RepositoryThrottlingMb
   Type : REG_DWORD

Throttling disables at 0. Any other value = bandwidth in MB/sec.

Operations:
  Schedule  - Apply throttling for current time window
  Test      - Show what the script would do
  Status    - Show current registry value
  Help      - Display this help

CRON/Scheduler: Use Task Scheduler to run hourly under SYSTEM
"@
    }
}
- Scheduled Task

Code: Select all

<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2024-08-14T00:00:00</Date>
    <Author>YourName</Author>
    <Description>Runs the VeeamBandwidthScheduler.ps1 script every 5 minutes to enforce time-based repository bandwidth throttling using the registry key Dev_RepositoryThrottlingMb.</Description>
    <URI>\Veeam Agent Bandwith Throttling Schedule - Scheduled Task</URI>
  </RegistrationInfo>
  <Triggers>
    <BootTrigger>
      <Enabled>true</Enabled>
    </BootTrigger>
    <CalendarTrigger>
      <Repetition>
        <Interval>PT5M</Interval>
        <StopAtDurationEnd>false</StopAtDurationEnd>
      </Repetition>
      <StartBoundary>2024-08-14T00:00:00</StartBoundary>
      <Enabled>true</Enabled>
      <ScheduleByDay>
        <DaysInterval>1</DaysInterval>
      </ScheduleByDay>
    </CalendarTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <UserId>S-1-5-18</UserId>
      <RunLevel>HighestAvailable</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>Queue</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>true</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>false</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>true</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
    <UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>PT10M</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>powershell.exe</Command>
      <Arguments>-NoProfile -ExecutionPolicy Bypass -File "C:\System\Veeambackup\VeeamBandwidthScheduler.ps1" -Operation Schedule</Arguments>
      <WorkingDirectory>C:\System\Veeambackup</WorkingDirectory>
    </Exec>
  </Actions>
</Task>
Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests