Welcome

Welcome to vPowerCLI.net, this blog will be focused on automating tasks for Veeam Backup & Replication via PowerShell, you can also follow us on twitter (@vPowerCLI) and I hope you enjoy the blog and find it useful.

v6 Remove and Add Target/Source Proxies

This script will allow you to remove Target Proxies and add in a target proxy in its place for replication job. I recently had a customer that needed to remove a target proxy from about 90 jobs so they could delete said target proxy. The reason the add target proxy section is also in the script, is so that you don’t remove your only target proxy from a job and wind up causing your jobs to fail.

Make sure to change the name on “Proxy to Delete” and “Proxy to Add”. If you need to do this for source proxy on a backup job or replica job, change $ProxyType to a 0.

asnp VeeamPSSnapin

$Jobs = Get-VBRJob | ?{$_.IsReplica}
# Target = 1; Source = 0
$ProxyType = 1
$ProxyToDelete = Get-VBRViProxy -Name "Proxy to Delete"
$ProxyToAdd = Get-VBRViProxy -Name "Proxy to Add"
foreach($Job in $Jobs)
{
    foreach($ProxyInfo in ([Veeam.Backup.DBManager.CDBManager]::Instance.JobProxies.GetJobProxies($Job.id, $ProxyType)))
    {
        if($ProxyInfo.ProxyId -eq $ProxyToDelete.id)
        {
            [Veeam.Backup.DBManager.CDBManager]::Instance.JobProxies.Delete($ProxyInfo.id)
            [Veeam.Backup.Core.CJobProxy]::Create($Job.id, $ProxyToAdd.id, $ProxyType)
        }
    }
}
By ReKoNiZe Posted in Veeam

Backup a single VM in a job

A great little workaround I discovered was posted on the Veeam forums for backing up a single VM in a job on v5/v6, what it does is adds all the VMs in the job to an exclusion list apart from the VM you would like to backup and triggers the job to run, once the job is completed the script will go ahead and remove the exclusions it placed on the job. I’ve included a little demo video of this for you to watch it in action but first let’s get you setup.

Save this to your hard-drive as a .ps1 file

#* Load Veeam snapin
Add-PsSnapin -Name VeeamPSSnapIn -ErrorAction SilentlyContinue
#* User Input
$jobName = Read-Host "Enter Job Name"
$vmName = Read-Host "Enter VM Name"

#* Find the job that has our VM
$job = Get-VBRJob | ?{$_.Name -eq $jobName}

#* Get all objects in job apart from our target VM
$execObjs = $job.GetObjectsInJob() | ?{$_.Name -ne $vmName}

#* Exclude the objects from the job(*Note: this isn't removing the objects
#* from the job)
Remove-VBRJobObject -Job $job -Objects $execObjs

#* Start the job only backing up the target VM
Start-VBRJob -Job $job

#* Find the exclude job objects
$incObjs = $job.GetObjectsInJob() | ?{$_.Type -eq "Exclude"}

#* Delete the exclude objects(*Note: this tells VBR to include them again
foreach ($obj in $incObjs) {
	$obj.Delete() | Out-Null
}

After that you can create a shortcut to the file or just right click the ps1 file and select “Run in Powershell”, if you would like a shortcut

  1. Right click the script.
  2. Select “Create Shortcut”.
  3. Drag shortcut to your desktop.
  4. Right click shortcut -> Properties
  5. Change the path to something like below.
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -File "C:\VeeamScripts\SingleVMBackup.ps1"

vPowerCLI v6 Army Report

Well this one took much longer than I ever anticipated but after some great help and support from Seth Bartlett (@sethbartlett) I managed to get it over the line and now ready to release her out to the world 🙂

The idea behind the report is to give you an overview of the backup environment, providing information that would normally be hard to see and enabling you to correct anything that isn’t being properly utilised.

Available Stats:

Job/Service Details vSphere Proxy Details Repository Details Replica Details
  • Coordinator
  • Total Jobs
  • Successful
  • Warning
  • Failed
  • Service Name
  • Service Status
  • Proxy Host
  • IP Address
  • Status
  • RT (ms)
  • Disabled
  • Read (GB)
  • Write (GB)
  • Utilisation (%)
  • Repository Name
  • Path
  • Free (GB)
  • Total (GB)
  • Free (%)
  • Replica Target
  • Datastore
  • Free (GB)
  • Total (GB)
  • Free (%)

Download: vPowerCLI v6 Army Report

The report can run in one of two ways, generate html file and open or send it via email and has very little configuration regardless of which one you choose, I would advised running through the different modes before setting it to email just incase anything unusual pops up

# File Output path and filename
$file = "C:\Scripts\Test.htm"
###############################
# report mode
# 24, 48, "Weekly", "Monthly"
$reportMode = 24
# Email configuration
$sendEmail = 0 #0 = No, 1 = Yes
$emailHost = "smtp.lab.local"
$emailUser = "Veeam@lab.local"
$emailPass = "MyPass"
$emailFrom = "Veeam@lab.local"
$emailTo = "john.doe@lab.local"
###############################

Create VBM From Scratch

So I’ve seen a handful of cases where a customer of Veeam may upgrade from version 5 to version 6 and maybe delete their jobs, have some issues during upgrade and be forced to start fresh, or just starting fresh from their own means. The issue that occurs with this is that you cannot use your existing 5 backups for 6 jobs without the jobs being ran once in version 6. Version 6 added a new file that is stored with your backup files now. It is a VBM file, short for Veeam Backup Metadata.

Here is a list of a few things the file holds:

  • Job ID
  • Job Name
  • JobSource Type
  • The host that the VMs are on(VC or ESX(i))
  • Storage information about the files that are contained in the backup chain
  • Restore points and how they are linked together
  • List of VMs

The last 3 bullet points actually have a lot more information that can be drilled into and can give you some very detailed information that I will not cover. The VBM file is just XML, so you can take a peek yourself if you’d like 😉

The script I wrote below(which needs to run in Administrator mode) will fire up a simple GUI with an “Import” button and some simple progress status during the process. All you have to do is point to the VBK of the backup chain you would like to create a VBM for and this script will do that. In a nutshell, it grabs the file, imports it into Veeam, creates a VBM from scratch and then looks for the repository that the VBM path would be on.

Enjoy 🙂

asnp "VeeamPSSnapIn" -ErrorAction SilentlyContinue
[reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
#Textfield Progress
$Progress = New-Object Windows.Forms.Label
$Progress.Text = "Progress: None"
$Progress.Location = New-Object Drawing.Point 64, 50
$Progress.Size = New-Object Drawing.Point 200, 100

#Button Setup
$Button = New-Object Windows.Forms.Button
$Button.text = "Import"
$Button.Location = New-Object Drawing.Point 65, 25

$Button.add_click(
{
	#Open Dialog Setup
	$Dialog = New-Object Windows.Forms.OpenFileDialog
	$Dialog.InitialDirectory = "C:\\"
	$Dialog.Filter = "VBK Files (*.vbk)|*.vbk"
	$Dialog.ShowHelp = $true
	$Dialog.ShowDialog()
	$Dialog.FileName -match "(?:.*\\)+(.+?)\d\d\d\d-\d\d-\d\dT\d\d\d\d\d\d\.vbk"

	#Veeam Setup
	$JobName = $Matches[1]
	$VeeamBox = Get-VBRLocalhost
	$Progress.Text = "Progress: Importing Backup"
	$FileName = $Dialog.FileName
	$Path = [System.IO.Path]::GetDirectoryName($Dialog.FileName)
	$VBMFile = $Path + "\" + $JobName + ".vbm"
	if(!([System.IO.File]::Exists($VBMFile)))
	{
		if(!(Get-VBRBackup -Name $JobName))
		{
			Import-VBRBackup -Server $VeeamBox -FileName $FileName
			$Backup = Get-VBRBackup -Name ($JobName + "_imported")
		}
		else
		{
			$Backup = Get-VBRBackup -Name $JobName
		}
		$Progress.Text = "Progress: Creating VBM File"
		$Data = [Veeam.Backup.Core.CBackupMetaGenerator]::GenerateMeta($Backup)
		$Data.Serialize() | Out-File $VBMFile
		$xml = New-Object XML
		$xml.Load($VBMFile)
		$xml.BackupMeta.JobName = $JobName
		$xml.Save($VBMFile)
		$Progress.Text = "Progress: Clean Up"
		Remove-VBRBackup -Backup $Backup -Confirm:$false
		$Progress.Text = "Progress: Repo Discovery"
		$Repository = Get-VBRBackupRepository | ?{$_.path -eq $Path}
		$TempRepository = New-Object Veeam.Backup.Core.CBackupRepositoryImporter -ArgumentList $Repository, 0
		$TempRepository.Import()
		$Progress.Text = "Progress: Finished"

	}
	else
	{
		$Progress.Text = "Failed: VBM Exists"
	}
})

#Form Setup
$Form = New-Object Windows.Forms.Form
$Form.Size = New-Object Drawing.Point 220,100
$Form.Text = "VBM Create"
$Form.Controls.Add($Button)
$Form.Controls.Add($Progress)
$Form.FormBorderStyle = "FixedDialog"
$Form.MaximizeBox = $false;
$Form.ShowDialog()
By ReKoNiZe Posted in Veeam

Disable/Enable the default v6 Proxy

Another small little post that a few of you will find useful, you may have noticed that you can’t seem to disable the “Default Proxy” that is created on your newly installed
v6 server, to work around this you can use the below PS code to Disable/Enable it, Anton has confirmed that switching it off won’t break anything and it’s just a small UI bug that will be sorted very soon.

  • Disable
#Disable the default proxy
$proxy = Get-VBRViProxy -Name "VMware Backup Proxy"
Disable-VBRViProxy -Proxy $proxy
  • Enable
#Enable the default proxy
$proxy = Get-VBRViProxy -Name "VMware Backup Proxy"
Enable-VBRViProxy -Proxy $proxy

Prefix Replica Names

*Caution*

One little nugget that I came across while exploring the new cmdlets in B&R v6 was the ability to prefix your replica names, I personally think this little feature is awesome as it saves you having to expand the inventory window to see which VMs have a “_Replica” suffix, I should point out that there is a small bug that’s currently being worked on by Veeam(once set you cannot change it via PS or GUI) so make sure your happy with the prefix before updating any of your jobs as it’s a PITA if you want to change it afterwards.

First thing to do is remove the old suffix from the job and then use the below code to apply your new prefix.

$job = Get-VBRJob -Name "Job Name"
$opt = $job | Get-VBRJobOptions
$opt.ViReplicaTargetOptions.ReplicaNamePrefix = "Replica_"
$job.SetOptions($opt)

Then just remove the VMs from the inventory(with the _Replica suffix) that are part of the job you changed.

If you didn’t heed my advice and made a mistake with the prefix, drop an email to vpowercli((at) remove me)vpowercli.net or reply below and I’ll talk you through the cleanup.

Get-vPCLastSessionExtended v5 cmdlet

This might be my last posting on the “Old” v5 shell since v6 is now GA but I still think this will be useful to people not making the jump to v6 straight away and I haven’t really had enough time to play with all the new cmdlets to see if you can do similar right out of the box.

So this cmdlet will get you a little more information from the last session including increment size, duration, speed, filename

Sample Output

Photobucket

Usage

Get-VBRJob | ?{$_.Name -eq "Job Name"} | Get-vPCLastSessionExtended

Feel free to include or distribute as you see fit 🙂

function Get-vPCLastSessionExtended {
	<# 
        .SYNOPSIS 
            Returns Extended information on the last session.

        .DESCRIPTION 
            Returns Extended infomation about the last session, including increment size, 
			duration, speed, filename etc
		
		.PARAMETER  ID 
            Specify job by ID.

        .EXAMPLE 
            PS C:\> Get-VBRJob | ?{$_.Name -eq "Job Name"} | Get-vPCLastSessionExtended
    #> 
	[CmdletBinding()]
	param (
		[Parameter(Position=0,
		ValueFromPipeline=$true,
		ValueFromPipelineByPropertyName=$true)]
		[Guid]$Id
		)
	PROCESS {
		$vPCBSEhash = @{}
		#Do some validation and get out of dodge if we don't have what we need
		$guidregx = "^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$"
		if ($Id -notmatch $guidregx) {
			Throw "Nothing to do, send me a jobID or Name"	
		}
		elseif ($Id -match $guidregx) {
			$jobID = $Id
		}
		
		#Function to add key and value to our hashtable
		function Add-vPCBSEShash ($key, $value) {
			$vPCBSEhash.Add($key, $value)
		}
		
		#Some arrays that we'll use
		$vPCBSEStats02a1 = @("JobId", "JobName", "JobSourceType", "JobTargetType",
							"State", "IsCompleted", "Failures",	"Warnings", 
							"IsRetryMode", "IsStartFullMode", "Result")
		$vPCBSEStats02a2 = @("TotalObjects", "TotalSize", "ProcessedObjects", 
							"ProcessedSize", "Progress", "StartTime", "StopTime", 
							"AvgSpeed", "Duration", "DisplayName")
		$vPCBSEStats02a3 = @("FileName", "DirPath")
		$vPCBSEStats02a4 = @("FilePath", "ModificationTime", "BlockSize")
		$vPCBSEStats02a5 = @("BackupSize", "DataSize", "DedupRatio", "CompressRatio")
		
		#Lets grab the last session stats
		$holdingobj = Get-VBRBackupSession | ?{$_.JobId -eq $jobID}
		$holdingobj | 
		Add-Member -Type NoteProperty -Name StartTime -Value ([System.DateTime])
		$holdingobj | 
		Add-Member -Type NoteProperty -Name StopTime -Value ([System.DateTime])
		$null = $holdingobj |
		%{($_.StartTime = $_.Info.CreationTime) -and ($_.StopTime = $_.Info.EndTime)}
		$holdingobj01 = $holdingobj | Sort StartTime -Descending | Select -First 1
		
		#Load the first set of stats into the hashtable
		$vPCBSEStats02a1 | %{Add-vPCBSEShash $_ $holdingobj01.Info."$_"}
		$vPCBSEStats02a2 | %{Add-vPCBSEShash $_ $holdingobj01.Progress."$_"}
		
		#Get the storage point that we want 
		$holdingobj = Get-VBRBackup | ?{$_.JobId -eq $jobID}
		$holdingobj01 = $holdingobj.GetStorages() | 
		sort CreationTime -Descending | Select -First 1
		
		#Load the second set of stats into the hashtable
		$vPCBSEStats02a3 | %{Add-vPCBSEShash $_ $holdingobj01."$_"}
		$vPCBSEStats02a4 | %{Add-vPCBSEShash $_ $holdingobj01.Info."$_"}
		$vPCBSEStats02a5 | %{Add-vPCBSEShash $_ $holdingobj01.Stats."$_"}
		#Build the output object
		$output = New-Object -TypeName PSObject -Property $vPCBSEhash
	}
	End {
			$output
	}
}

Bring order to the Get-VBRBackupSession cmdlet, Get-vPCBackupSession

While contributing to a post over in the Veeam forums we discovered that the Get-VBRBackupSession cmdlet was darn near impossible to get in any sort of order, which made it pretty useless, so I wrote this cmdlet to fix the issue

function Get-vPCBackupSession {
	<# 
        .SYNOPSIS 
            Returns backup sessions.

        .DESCRIPTION 
            Returns objects of all backup job sessions that have been run. You can also 
			specify a job name and limit.

        .PARAMETER  JobName 
            Filter results or returned sessions.
		
		.PARAMETER  Limit 
            Limit the amount of records returned.

        .EXAMPLE 
            PS C:\> Get-vPCBackupSession -JobName "Job Name" -Limit 10

        .EXAMPLE 
            PS C:\> Get-VBRJob | ?{$_.Name -eq "Job Name"} | Get-vPCBackupSession -Limit 10
		
		.EXAMPLE 
            PS C:\> Get-VBRJob | %{Get-vPCBackupSession $_.Name -Limit 3}
    #> 
	[CmdletBinding()]
	param (
		[Parameter(
		Position=0, 
		ValueFromPipeline=$true,
		ValueFromPipelineByPropertyName=$true)
		]
		[Alias('Name')]
		[String]$JobName,
		[Int]$Limit
	)
	PROCESS {
		if ( $JobName.ToString().Trim() -eq "" ) 
		{
			$vPCBS = Get-VBRBackupSession
		}
		else
		{
			$jobID = Get-VBRJob | ?{$_.Name -eq $JobName}
			$vPCBS = Get-VBRBackupSession | ?{$_.JobId -eq $jobID.Id}
		}
		$vPCBS | Add-Member -type NoteProperty -name StartTime -value ([System.DateTime])
		$vPCBS | Add-Member -type NoteProperty -name StopTime -value ([System.DateTime])
		$vPCBS | 
		%{($_.StartTime = $_.Info.CreationTime) -and ($_.StopTime = $_.Info.EndTime)} | 
		Out-Null
		if ( $Limit -le 0)
		{
			$output = $vPCBS | Sort StartTime -Descending
		}
		else
		{
			$output = $vPCBS | Sort StartTime -Descending | Select -First $Limit
		}
	}
	End {
			$output
	}
}

Its usage is pretty simply

Get-vPCBackupSession -JobName "Job Name" -Limit 10
Get-VBRJob | ?{$_.Name -eq "Job Name"} | Get-vPCBackupSession -Limit 10
Get-VBRJob | %{Get-vPCBackupSession $_.Name -Limit 3}

What it basically does is go through the backup sessions and brings the CreationTime and EndTime to the root level with the name of StartTime and StopTime respectively(default sort is StartTime -Descending), which allows us to sort the results by either property.

Changing Veeam B&R v5 NFS Paths

Didn’t pay attention to this setting when you installed B&R? Running out of space on you current store? Not to worry, there is a script for that :). I would have posted this earlier but it occurred to me that if I’m putting these scripts into the wild then I better start doing some basic checks, this script will check your new NFS path and make sure it has been created before it updates the registry with the new values, makes sure that the keys we want to update are in the registry, doesn’t care if you’re on 32 or 64 bit OS and a little bit of meaningful info should anything not go to plan.

$arch = $ENV:Processor_Architecture
$vepath1 = "Veeam Backup and Replication"
$vepath2 = "Veeam NFS\Shared Folders"
$vekn1 = "NFSDefaultRootPath"
$vekn2 = "localFolderPath"
$newpath = Read-Host("Please enter new path")
function FR-Check ([string]$ckpath) {
	Test-Path -Path "$ckpath"
}
function Do-TheBiz ([string]$ukpath) {
	$i = 0
	if ( -not ( FR-Check "$ukpath\$vepath1" )) {
 		Write-Warning "Couldn't find Key 1, are you sure Veeam B&R is installed"
		Write-Host "No Keys have been updated."
		exit
 	} else {
 		Set-ItemProperty -Path "$ukpath\$vepath1" -Name "$vekn1" -Value "$newpath"
		$i ++
 	}
 	if ( -not ( FR-Check "$ukpath\$vepath2\{*}" )) {
 		Write-Host "Key 2 wasn't found but that isn't a bad thing."	
 	} else {
 		Set-ItemProperty -Path "$ukpath\$vepath2\{*}" -Name "$vekn2" -Value "$newpath"
		$i ++
 	}
	if ( $i -eq 1) {
		Write-Host "$i Key has been updated. Please restart Veeam Services."
	} else {
		Write-Host "$i or more Keys have been updated. Please restart Veeam Services."
	}
}
if ( -not ( FR-Check "$newpath" )) {
	Write-Warning "New Path Not Found! Please fix this."
	exit
}
if ( $arch -eq "x86") {
	Do-TheBiz "HKLM:\SOFTWARE\Veeam"
} elseif ( $arch -eq "AMD64" ) {
	Do-TheBiz "HKLM:\SOFTWARE\Wow6432Node\Veeam"
} else {
	Write-Host "I couldn't tell if we are on 32/64 bit OS"
}

Copy Existing Veeam Back-up Job

I’ve been involved in a post over at the Veeam forums about how to copy an existing B&R job, while the GUI doesn’t provide a way to do it in v5 you should have been able to easily achieve this with PowerShell via the below command

Get-VBRJob | ?{$_.Name -eq "Test Job"} | Copy-VBRJob

Unfortunately the above will only partial work, it will also display an error regarding a folder not found with a long code of zeros and dashes and won’t copy the VMs in the original job over to the new one, Seth Bartlett from Veeam has confirmed;

Some older folder-id information seems to be in the code

So if you need to do this, below is a script that I came up with as a workaround until this has been resolved.

Add-PsSnapin -Name VeeamPSSnapIn
$uinput = Read-Host "Enter Job Name"
function Add-JO{
  Param ([string]$vmname)
  $newjob =  Get-VBRJob | ?{$_.Name -eq "$uinput Copy"}
  $vbrserver = Get-VBRServer | ?{$_.Type -eq "VC"}
  Add-VBRJobObject -Job $newjob -Server $vbrserver -Object $vmname
}
Get-VBRJob | ?{$_.Name -eq $uinput} | Copy-VBRJob -ErrorAction SilentlyContinue
Get-VBRJob | ?{$_.Name -eq $uinput} | Get-VBRJobObject | ForEach-Object {Add-JO $_.Name}

This will copy over the VMs after it has created the copy job, not ideal but should do for now and if you intend to run it multiple times please make sure you rename the copy in between runs.