Category Archives: Veeam

Veeam: Bitlooker & Powershell


In this post I will share some Powershell code to enable or disable the feature BitLooker for your Veeam jobs. Since Bitlooker is a “new” feature you have to enable it on your jobs that are created before you installed Veeam v9 or higher. I my case we are running Veeam Backup for quite some years now, so we had to enable this feature on hundreds of jobs. Once again Powershell to the rescue.

Bur first things first, what is Bitlooker?

With this option enabled, Veeam Backup & Replication performs the following operations during the job session:

  1. Veeam Backup & Replication accesses the MFT file on the VM guest OS to identify deleted file blocks, and zeros out these blocks.
  2. Veeam Backup & Replication processes and transports data blocks of the VM image in the following manner:
  • If a data block of the VM image contains only the deleted file blocks, Veeam Backup & Replication does not read this data block from the source datastore.
  • If a data block of the VM image contains zeroed out blocks and other data, Veeam Backup & Replication copies this block to the target. Due to data compression, data blocks that are marked as deleted are compressed, and the size of the resulting backup or replica file reduces.

source: https://helpcenter.veeam.com/docs/backup/vsphere/dirty_blocks.html?ver=95

You can find the Exclude delete file blocks option in the job configuration wizard under Storage – Advanced – Storage. This option is enabled by default if you configured the job after you installed Veeam v9 but is disabled on jobs created before the installation or upgrade to Veeam v9. See the screenshot below:

image

Well that’s great this new option but I need to configure this setting for hundreds or maybe even more jobs. Is this possible via Powershell? On the Veeam forum you can find a sample script written by v.Eremin. This script will enable this setting right away with no interaction to the user. I wanted to create a script so I was able to see which jobs needs to be configured. So I came up with the following script:

Add-PSSnapin VeeamPSSnapIn

Connect-VBRServer -Server VEEAM-SRV01.DOMAIN.LOCAL

$BitlookerInfo = @()
$AllVbrJobs = Get-VBRJob
$AllVbrJobsCount = ($AllVbrJobs | Measure).Count
$VeeamBackupServer = (Get-VBRLocalhost | Select -ExpandProperty Name).ToUpper()
Write-Output "Checking Veeam Server: $($VeeamBackupServer) ..."
Write-Output ''
$AllVbrJobsDirtyBlocksNullingDisabled = $AllVbrJobs | ?{$_.Options.ViSourceOptions.DirtyBlocksNullingEnabled -eq $False}
$AllVbrJobsDirtyBlocksNullingDisabled | %{
    $BitlookerInfo += New-Object PSCustomObject -Property @{
        BackupServer = $VeeamBackupServer
        Name = $_.Name
        ExcludeDeletedFileBlocks = $_.Options.ViSourceOptions.DirtyBlocksNullingEnabled
    }

    foreach($job in $BitlookerInfo){
        $vbrjob = Get-VBRJob -Name $job.Name
        Write-Output "Job: $($vbrjob.Name)"
        $options = $vbrjob.GetOptions()
        $options.ViSourceOptions.DirtyBlocksNullingEnabled = $true
        $vbrjob.SetOptions($options)
    }

}

$AllBitlookerDisabledJobsCount = ($BitlookerInfo | Measure).Count
Write-Output "Total Veeam jobs: $($AllVbrJobsCount)"
Write-Output "Total Veeam jobs where Bitlooker is enabled: $($AllBitlookerDisabledJobsCount)"
Write-Output ''
$BitlookerInfo | Sort Name | ft -AutoSize

Disconnect-VBRServer

This is the output of the script:

Checking Veeam Server: VEEAM-SRV01.DOMAIN.LOCAL …

Total Veeam jobs: 2
Total Veeam jobs where Bitlooker is enabled: 1

Name              BackupServer                              ExcludeDeletedFileBlocks
—-                   ————                                      ————————
Demo-Job-01 VEEAM-SRV01.DOMAIN.LOCAL    False

You can add a for each loop to loop through the Veeam Backup & Replication servers you configured. This will look like this:

Add-PSSnapin VeeamPSSnapIn $AllVeeamServers = @("VEEAM-SRV01.DOMAIN.LOCAL","VEEAM-SRV02.DOMAIN.LOCAL","VEEAM-SRV03.DOMAIN.LOCAL","VEEAM-SRV04.DOMAIN.LOCAL") foreach($VeeamServer in $AllVeeamServers){ Connect-VBRServer -Server $VeeamServer $BitlookerInfo = @() $AllVbrJobs = Get-VBRJob $AllVbrJobsCount = ($AllVbrJobs | Measure).Count $VeeamBackupServer = (Get-VBRLocalhost | Select -ExpandProperty Name).ToUpper() Write-Output "Checking Veeam Server: $($VeeamBackupServer) ..." Write-Output '' $AllVbrJobsDirtyBlocksNullingDisabled = $AllVbrJobs | ?{$_.Options.ViSourceOptions.DirtyBlocksNullingEnabled -eq $False} $AllVbrJobsDirtyBlocksNullingDisabled | %{ $BitlookerInfo += New-Object PSCustomObject -Property @{ BackupServer = $VeeamBackupServer Name = $_.Name ExcludeDeletedFileBlocks = $_.Options.ViSourceOptions.DirtyBlocksNullingEnabled } foreach($job in $BitlookerInfo){ $vbrjob = Get-VBRJob -Name $job.Name Write-Output "Job: $($vbrjob.Name)" $options = $vbrjob.GetOptions() $options.ViSourceOptions.DirtyBlocksNullingEnabled = $true $vbrjob.SetOptions($options) } } $AllBitlookerDisabledJobsCount = ($BitlookerInfo | Measure).Count Write-Output "Total Veeam jobs: $($AllVbrJobsCount)" Write-Output "Total Veeam jobs where Bitlooker is enabled: $($AllBitlookerDisabledJobsCount)" Write-Output '' $BitlookerInfo | Sort Name | ft -AutoSize Disconnect-VBRServer }

Powershell: Veeam Cloud Connect total virtual machines report


The PowerShell script below helps you to create a simple overview of your Veeam Cloud Connect environment. The environment where this script is developed in consist of two Veeam Cloud Connect Backup servers. The first server will be used for the Cloud Connect Backup solution and the second server will be used for the Cloud Connect Replica server. To connect to these servers we use the Connect-VBRServer cmdlet. I personally love this new cmdlet. It just works like the Connect-VIServer cmdlet. The script will get all the Cloud Tenants and gathers usage information, for Backup tenants only, and will return the total number of virtual machines. At the end of the script all the information will be bundled into a html report. This report will be send to the recipients defined in the $MailReportTo variable.

Add-PSSnapin VeeamPSSnapIn
$AllVccServers = @("vccr-bs01.lab.loc","vccb-bs01.lab.loc")

$MailReportTo = @("user1@domain.com","user2@doman.com")
$MailReportSubject = "Veeam Cloud Connect - Total virtual machines report"
$MailReportFrom = "$(hostname)@domain.com"
$MailReportSmtpServer = "smtp.domain.com"

$VeeamTenantInfo = @()
foreach($VccBackupServer in $AllVccBackupServers){
    Write-Output "Connecting to Veeam Cloud Connect Backup Server $($VccBackupServer)"
    Connect-VBRServer -Server $VccBackupServer

    foreach($VBRCloudTenant in (Get-VBRCloudTenant | Sort Name)){
        
        $RepositoryQuota = $([math]::Truncate($VBRCloudTenant.Resources.RepositoryQuota / 1024))
        $UsedSpace = $([math]::Truncate($VBRCloudTenant.Resources.UsedSpace / 1024))
        $UsedSpacePercentage = $VBRCloudTenant.Resources.UsedSpacePercentage
        $Repository = $VBRCloudTenant.Resources.Repository.name
        $Leaseperiod = $VBRCloudTenant.LeaseExpirationDate


        if($Repository -eq $null -and $VBRCloudTenant.ReplicaCount -ne 0){
            $UsedSpace = 0
            $Repository = 0
            $RepositoryQuota = 0
            $UsedSpacePercentage = 0
            $Repository = "n.a."
        }
        
        if($Leaseperiod -eq $null){
            $Leaseperiod = "n.a."
        }

        $VeeamTenantInfo += New-Object PSObject -Property ([ordered]@{
            User = $VBRCloudTenant.Name
            Enabled = $VBRCloudTenant.Enabled
            VMCount = $VBRCloudTenant.VMCount
            ReplicaCount = $VBRCloudTenant.ReplicaCount
            RepositoryQuota = $RepositoryQuota
            UsedSpace = $UsedSpace
            UsedSpacePercentage = $UsedSpacePercentage
            Repository = $Repository 
            LeaseExpirationEnabled = $VBRCloudTenant.LeaseExpirationEnabled
            LeaseExpirationDate = $Leaseperiod
        })
    }
    Disconnect-VBRserver
}

$html = "<html><body><h1>Veeam Cloud Connect</h1><table border=1 cellspacing=0 cellpadding=3>"
$html += "<html><body><h2>Cloud Connect Server: $((hostname).ToUpper())</h2><table border=1 cellspacing=0 cellpadding=3>"
$html += "<html><body><h3>Usage report generated on $(Get-Date -Format g)</h3><table border=1 cellspacing=0 cellpadding=3>"
$html += "<tr>"
$html += "<th>User</th>"
$html += "<th>Enabled</th>"
$html += "<th>VMCount</th>"
$html += "<th>ReplicaCount</th>"
$html += "<th>RepositoryQuota in GB</th>"
$html += "<th>UsedSpace in GB</th>"
$html += "<th>UsedSpacePercentage</th>"
$html += "<th>Repository</th>"
$html += "<th>LeaseExpirationEnabled</th>"
$html += "<th>LeaseExpirationDate</th>"
$html += "</tr>"
foreach($veeamTenant in $VeeamTenantInfo){
    $html += "<tr>"
    $html += "<td>$($veeamTenant.User)</td>"
    $html += "<td>$($veeamTenant.Enabled)</td>"
    $html += "<td>$($veeamTenant.VMCount)</td>"
    $html += "<td>$($veeamTenant.ReplicaCount)</td>"
    $html += "<td>$($veeamTenant.RepositoryQuota)</td>"
    $html += "<td>$($veeamTenant.UsedSpace)</td>"
    $html += "<td>$($veeamTenant.UsedSpacePercentage)</td>"
    $html += "<td>$($veeamTenant.Repository)</td>"
    $html += "<td>$($veeamTenant.LeaseExpirationEnabled)</td>"
    $html += "<td>$($veeamTenant.LeaseExpirationDate)</td>"
    $html += "</tr>"
}
$html += "<tr>"
$html += "<td colspan=2><b>Totaal</b></td>"
$html += "<td>$(($VeeamTenantInfo.VMCount | Measure -Sum).sum)</td>"
$html += "<td>$(($VeeamTenantInfo.ReplicaCount | Measure -Sum).sum)</td>"
$html += "<td>$(($VeeamTenantInfo.RepositoryQuota | Measure -Sum).sum)</td>"
$html += "<td>$(($VeeamTenantInfo.UsedSpace | Measure -Sum).sum)</td>"
$html += "<td></td>"
$html += "<td></td>"
$html += "<td></td>"
$html += "<td></td>"
$html += "</tr>"
$html += "</table></body></html>"

$ScriptBaseName = ((gci ([string]$MyInvocation.InvocationName)).FullName) -replace "\.ps1$", ''
$html | Out-File "$($ScriptBaseName)_$(Get-date -Format yyyyMM).log.html"

try{
    if ($MailReportTo -eq $null){ throw [Exception]"No To address specified" }
    if ($MailReportSubject -eq $null) { throw [Exception]"No Subject specified" }
    if ($MailReportFrom -eq $null){ throw [Exception]"No From address specified" }
    if ($MailReportSmtpServer -eq $null) { throw [Exception]"No Smtp server specified" }
    Send-MailMessage -BodyAsHtml -Body $html -From $MailReportFrom -SmtpServer $MailReportSmtpServer -To $MailReportTo -Subject $MailReportSubject
    Write-Output "Mail message sent to $MailReportTo"
}
catch
{
    Write-Error "Error sending mail: $($_.Exception.Message)."
}

The report will look like this:

image

If you don’t want to use the html report. Use the code below to generate the report directly in the Powershell console.

Add-PSSnapin VeeamPSSnapIn
$AllVccServers = @("vccr-bs01.lab.loc","vccb-bs01.lab.loc")

$VeeamTenantInfo = @()
foreach($VccBackupServer in $AllVccBackupServers){
    Write-Output "Connecting to Veeam Cloud Connect Backup Server $($VccBackupServer)"
    Connect-VBRServer -Server $VccBackupServer

    foreach($VBRCloudTenant in (Get-VBRCloudTenant | Sort Name)){
        
        $RepositoryQuota = $([math]::Truncate($VBRCloudTenant.Resources.RepositoryQuota / 1024))
        $UsedSpace = $([math]::Truncate($VBRCloudTenant.Resources.UsedSpace / 1024))
        $UsedSpacePercentage = $VBRCloudTenant.Resources.UsedSpacePercentage
        $Repository = $VBRCloudTenant.Resources.Repository.name
        $Leaseperiod = $VBRCloudTenant.LeaseExpirationDate


        if($Repository -eq $null -and $VBRCloudTenant.ReplicaCount -ne 0){
            $UsedSpace = 0
            $Repository = 0
            $RepositoryQuota = 0
            $UsedSpacePercentage = 0
            $Repository = "n.a."
        }
        
        if($Leaseperiod -eq $null){
            $Leaseperiod = "n.a."
        }

        $VeeamTenantInfo += New-Object PSObject -Property ([ordered]@{
            User = $VBRCloudTenant.Name
            Enabled = $VBRCloudTenant.Enabled
            VMCount = $VBRCloudTenant.VMCount
            ReplicaCount = $VBRCloudTenant.ReplicaCount
            RepositoryQuota = $RepositoryQuota
            UsedSpace = $UsedSpace
            UsedSpacePercentage = $UsedSpacePercentage
            Repository = $Repository 
            LeaseExpirationEnabled = $VBRCloudTenant.LeaseExpirationEnabled
            LeaseExpirationDate = $Leaseperiod
        })
    }
    Disconnect-VBRserver
}
$VeeamTenantInfo

Powershell: Change Veeam San Snapshot Options


In the case you want to use the Storage Snapshot feature with Veeam Backup, the feature will be enabled for all the Backup jobs and will be the default option to process a backup job.
Screenshot 2016-01-22 11.53.51

We only want to enable the feature for certain jobs with a special name convention like SAN-BackupJob-01. So I created a small Powershell script to disable this feature for all the jobs without the special name convention.

The Powershell script below will return all the jobs where the job name not match the “SAN” search string. The next step is to disable the “Use storage snapshots” feature for the jobs.

Script: Disable-SanIntegrationOptions.ps1:

if((Get-PSSnapin -Name VeeamPSSnapIn -ErrorAction SilentlyContinue) -eq $null){
    Add-PSSnapin "VeeamPSSnapIn"
}

foreach($vbrjob in (get-vbrjob | ?{$_.Name -notmatch "SAN"})){
    Write-Output "Changing job: $($vbrjob.name).."
    $SanIntegrataionOptions = $vbrjob.GetOptions()
    $SanIntegrataionOptions.SanIntegrationOptions.UseSanSnapshots = $false

    $vbrjob.SetOptions($SanIntegrataionOptions)
}

From now on only the jobs that need the SAN Snapshot feature, can utilise this feature and all the other jobs will use the default processing mode.

Veeam: End of support Veeam 6.5 in Q4 2014 with the release of v8


A quote from Gostev, in the Veeam Community Forums Digest mailing, send on august 4:

If you, or your customers are still using B&R 6.5, please keep in mind that we will stop supporting this version along with our v8 release, which is planned for early Q4. So please take the opportunity of slow summer time to perform the upgrade to v7. New releases typically increase load on our technical support team, which may in turn increase response times to handle possible upgrade issues (although frankly, we are not getting a lot of those for v7).

So if you’re still using Veeam 6.5 in production. Start working on your RFC to upgrade to Veeam v7.

Veeam v7: How to change the Job notification settings with Powershell


In an earlier post you will find a Powershell script to change the VM Notes setting in Veeam Backup. This old script worked for previous version of Veeam Backup and Replication.

image_thumb[2]

In Veeam Backup v7 the Powershell code is a little bit changed so I had to rewrite the script.  The script below will enable the VM notes for a job, if the option is disabled.

if((Get-PSSnapin -Name VeeamPSSnapIn -ErrorAction SilentlyContinue) -eq $null){
    Add-PSSnapin "VeeamPSSnapIn"
}

foreach($vbrjob in (get-vbrjob | Sort Name)){
    $options = $vbrjob.GetOptions()
    if($options.ViSourceOptions.SetResultsToVmNotes -eq $false){
        $options.ViSourceOptions.SetResultsToVmNotes = $true
        Write-Host "Enable set results to VM notes for job $($vbrjob.Name)"    
    }
    $vbrjob.SetOptions($options)
}    

Veeam: A file level restore gets stuck in a "stopping" state.


Today a colleague of mine was trying to perform a file level restore on one of the Veeam servers. But unfortunately the job became unresponsive and got stuck in a stopping state. See the print screen below:

image

To fix this issue, you need to run a SQL query on the Veeam database to clear the locks. I have included the solution form KB1534:

Problem:

A file level restore gets stuck in a "stopping" or "starting" state.

Cause:

This issue typically occurs when the VeeamBackup database has become out of sync with Veeam and the true state of the File Level Restore is not updated in the GUI.

Solution:

To fix this you will need to run a SQL query against the VeeamBackup Database, instructions are as shown below. 
Before running this SQL query against the “VeeamBackup” Database, please make sure that there are currently no jobs running. If you are unaware of how to run a query against a DB please read the steps below, if you are aware please disregard.
1.       Open up SQL Server Management Studio and connect to the VEEAM instance.
2.       Expand “Databases”.
3.       Right-click “VeeamBackup”>New query.
4.       Paste the query below into the query window and hit either “execute” or F5.

The query:

UPDATE [ReportRestoreSessionsAndTaskSessionsView]
   SET "state" = -1 
    WHERE "initiator_name" not like 'null'

After running the query and restarting the Veeam console. My colleague was able to perform the file level restore.

Source: http://www.veeam.com/kb1534

Veeam: Host with uuid <uuid> was not found


Today I saw a new error with Veeam Backup and Replication. The error was:

Host with uuid “<uuid>” was not found

Within the Veeam console it looks like this:

image

After a quick search in the Veeam knowledge base I found the Knowledge base article with KB1063.

To fix this issue from the GUI go to Help – License – Licensed Hosts and revoke the license of the host with the new installation.

You can also remove all the licensed hosts via a MS SQL query on the de SQL Database by running the query below:

delete from [dbo].[HostsByJobs]

The reason for this error was a rebuild of the ESXi host.

Source: http://www.veeam.com/kb1063