Find the latest version here.
Here’s another case of taking a script that someone has shared and putting your personal tweaks into it.
If there was an area in which I wish Veeam would improve, it would be reporting. Though their answer is VeeamOne, it’s a bit much if you just want the additional backup reports. Fortunately this can be overcome with some creative Powershell. I started with a report called vPowerCLI v6 Army Report which can be found here. I had used this report for quite a while until v7 came along and broke a few items. I decided to take the opportunity to not only fix the issues (where I could) but also add some information to the report. I had also been looking at the SAMReports found here and decided to combine a few bits. Lastly, Tom Sightler had a post here that added the ability to report back VMs that had not been backed up within the given time frame – very nice. I can’t say enough about the original authors, without which, I never could have come up with such a report in the end.
Report info includes
- Job/Session details over period of time (12,24,Week,Month)
- VMs with no successful backups
- Running sessions
- Sessions with warnings or failures with session level details
- Repository Details
- Proxy Details
- Veeam Services Details
- License/Support Renewal Date
Update the User-Variables section to suit your needs.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
asnp "VeeamPSSnapIn" -ErrorAction SilentlyContinue | |
#region User-Variables | |
# Report Title | |
$rptTitle = "My Veeam Report" | |
# Report mode – valid modes: any number of hours, Weekly or Monthly | |
# 24, 48, "Weekly", "Monthly" | |
$reportMode = 24 | |
# File Output path and filename | |
# When $sendEmail is set to $false, file is created and opened in default browser | |
$file = "E:\MyVeeamReport.htm" | |
# Show VMs with no successful backups within time frame ($reportMode) | |
$showMissing = $true | |
# vCenter server(s) – As seen in VBR server | |
#$vcenters = "vcenter1","vcenter2" | |
$vcenters = "vcenter.yourdomain.local" | |
# To Exclude VMs from Missing Backups report add VM names to be excluded as follows | |
# $excludevms = @("vm1","vm2","*_replica") | |
$excludeVMs = @("") | |
# Exclude VMs from Missing Backups report in the following (vcenter) folder | |
$folderExclude = "" | |
# Show jobs w/warnings or errors | |
$jlines = $true | |
# Show running jobs | |
$rlines = $true | |
# Show running Services | |
$runningSvc = $false | |
# Location of Veeam executable (Veeam.Backup.Manager.exe) | |
$veeamExePath = "C:\Program Files\Veeam\Backup and Replication\Backup\Veeam.Backup.Shell.exe" | |
# Location of common dll – Needed for repository function – Get-vPCRepoInfo | |
$veeamDllPath = "C:\Program Files\Veeam\Backup and Replication\Backup\Veeam.Backup.Common.dll" | |
# Email configuration | |
# Send Email – $true or $false – if true, email is sent, if false, output is saved to $file | |
$sendEmail = $false | |
$emailHost = "smtprelay.yourdomain.local" | |
$emailUser = "" | |
$emailPass = "" | |
$emailFrom = "MyVeeamReport@yourdomain.local" | |
$emailTo = "you@yourdomain.local" | |
# Send report as attachment – $true or $false | |
$emailAttach = $false | |
# Highlighting Thresholds | |
# Repository Free Space Remaining % | |
$repoCritical = 10 | |
$repoWarn = 20 | |
# Replica Target Free Space Remaining % | |
$replicaCritical = 10 | |
$replicaWarn = 20 | |
# License Days Remaining | |
$licenseCritical = 30 | |
$licenseWarn = 90 | |
#endregion | |
#region VersionInfo | |
$vPCARversion = "1.1.4" | |
# | |
# Version 1.1.4 – SM | |
# Misc tweaks/bug fixes | |
# Reconfigured HTML a bit to help with certain email clients | |
# Added cell coloring to highlight status | |
# Added $rptTitle variable to hold report title | |
# Added ability to send report via email as attachment | |
# | |
# Version 1.1.3 – SM | |
# Added Details to Sessions with Warnings or Failures | |
# | |
# Version 1.1.2 – SM | |
# Minor tweaks/updates | |
# Added Veeam version info to header | |
# | |
# Version 1.1.1 – Shawn Masterson | |
# Based on vPowerCLI v6 Army Report (v1.1) by Thomas McConnell | |
# http://www.vpowercli.co.uk/2012/01/23/vpowercli-v6-army-report/ | |
# http://pastebin.com/6p3LrWt7 | |
# | |
# Tweaked HTML header (color, title) | |
# | |
# Changed report width to 1024px | |
# | |
# Moved hard-coded path to exe/dll files to user declared variables ($veeamExePath/$veeamDllPath) | |
# | |
# Adjusted sorting on all objects | |
# | |
# Modified info group/counts | |
# Modified – Total Jobs = Job Runs | |
# Added – Read (GB) | |
# Added – Transferred (GB) | |
# Modified – Warning = Warnings | |
# Modified – Failed = Failures | |
# Added – Failed (last session) | |
# Added – Running (currently running sessions) | |
# | |
# Modified job lines | |
# Renamed Header – Sessions with Warnings or Failures | |
# Fixed Write (GB) – Broke with v7 | |
# | |
# Added support license renewal | |
# Credit – Gavin Townsend http://www.theagreeablecow.com/2012/09/sysadmin-modular-reporting-samreports.html | |
# Original Credit – Arne Fokkema http://ict-freak.nl/2011/12/29/powershell-veeam-br-get-total-days-before-the-license-expires/ | |
# | |
# Modified Proxy section | |
# Removed Read/Write/Util – Broke in v7 – Workaround unknown | |
# | |
# Modified Services section | |
# Added – $runningSvc variable to toggle displaying services that are running | |
# Added – Ability to hide section if no results returned (all services are running) | |
# Added – Scans proxies and repositories as well as the VBR server for services | |
# | |
# Added VMs Not Backed Up section | |
# Credit – Tom Sightler – http://sightunseen.org/blog/?p=1 | |
# http://www.sightunseen.org/files/vm_backup_status_dev.ps1 | |
# | |
# Modified $reportMode | |
# Added ability to run with any number of hours (8,12,72 etc) | |
# Added bits to allow for zero sessions (semi-gracefully) | |
# | |
# Added Running Jobs section | |
# Added ability to toggle displaying running jobs | |
# | |
# Added catch to ensure running v7 or greater | |
# | |
# | |
# Version 1.1 | |
# Added job lines as per a request on the website | |
# | |
# Version 1.0 | |
# Clean up for release | |
# | |
# Version 0.9 | |
# More cmdlet rewrite to improve perfomace, credit to @SethBartlett | |
# for practically writing the Get-vPCRepoInfo | |
# | |
# Version 0.8 | |
# Added Read/Write stats for proxies at requests of @bsousapt | |
# Performance improvement of proxy tear down due to rewrite of cmdlet | |
# Replaced 2 other functions | |
# Added Warning counter, .00 to all storage returns and fetch credentials for | |
# remote WinLocal repos | |
# | |
# Version 0.7 | |
# Added Utilisation(Get-vPCDailyProxyUsage) and Modes 24, 48, Weekly, and Monthly | |
# Minor performance tweaks | |
#endregion | |
#region NonUser-Variables | |
# Get the B&R Server | |
$vbrServer = Get-VBRLocalHost | |
# Get all the VI proxies in your army | |
$viProxyList = Get-VBRViProxy | |
# Get all the backup repositories | |
$repoList = Get-VBRBackupRepository | |
# Get unique repo servers | |
$uniqueRepos = @() | |
$repolist | %{$uniqueRepos += $($_.gethost().realname)} | |
$uniqueRepos = $uniqueRepos | Sort -unique | |
# Get all sessions to determine working jobs | |
$allSesh = Get-VBRBackupSession | |
# Get all the backup sessions for mode | |
if ($reportMode -eq "Monthly") { | |
$HourstoCheck = 720 | |
} elseif ($reportMode -eq "Weekly") { | |
$HourstoCheck = 168 | |
} else { | |
$HourstoCheck = $reportMode | |
} | |
$seshList = $allSesh | ?{($_.CreationTime -ge (Get-Date).AddHours(-$HourstoCheck)) -and ($_.State -ne "Working")} | |
if (($reportMode -ne "Weekly") -And ($reportMode -ne "Monthly")) { | |
$rptTitle = "$rptTitle (Last $reportMode Hrs)" | |
} else { | |
$rptTitle = "$rptTitle ($reportMode)" | |
} | |
#Get replica jobs | |
$repList = Get-VBRJob | ?{$_.IsReplica} | |
# Get the job counts | |
$totalxfer = $null | |
$totalRead = $null | |
$seshList | %{$totalxfer += $([Math]::Round([Decimal]$_.Progress.TransferedSize/1GB, 2))} | |
$seshList | %{$totalRead += $([Math]::Round([Decimal]$_.Progress.ReadSize/1GB, 2))} | |
$succesSessions = @($seshList | ?{$_.Result -eq "Success"}) | |
$warningSessions = @($seshList | ?{$_.Result -eq "Warning"}) | |
$failsSessions = @($seshList | ?{$_.Result -eq "Failed"}) | |
$totalSessions = @($seshList | ?{$_.Result -eq "Failed" -Or $_.Result -eq "Success" -Or $_.Result -eq "Warning"}) | |
$runningSessions = @($allSesh | ?{$_.State -eq "Working"}) | |
$failedSessions = @($seshList | ?{($_.Result -eq "Failed") -and ($_.WillBeRetried -ne "True")}) | |
#endregion | |
#region Functions | |
function Get-vPCProxyInfo { | |
[CmdletBinding()] | |
param ( | |
[Parameter(Position=0)] | |
[String[]]$Name, | |
[Parameter(Mandatory=$true, Position=1)] | |
[PSObject[]]$Sessions | |
) | |
Begin { | |
$vPCObjAry = @() | |
[Int]$script:jobcount = 0 | |
[Int]$totalObjInJob = 0 | |
$cleanSessions = $Sessions | ?{($_.Result -ne "Failed") -and | |
($_.State -eq "Stopped") -and ($_.JobType -ne "Copy")} | |
$cleanSessions | %{$totalObjInJob = $totalObjInJob + $_.Progress.TotalObjects} | | |
Out-Null | |
function Build-vPCObj {param ([PsObject]$inputObj) | |
$ping = new-object system.net.networkinformation.ping | |
$pinginfo = $ping.send("$($inputObj.Host.RealName)") | |
if ($pinginfo.Status -eq "Success") { | |
$hostAlive = "Alive" | |
} else { | |
$hostAlive = "Dead" | |
} | |
$vPCFuncObject = New-Object PSObject -Property @{ | |
ProxyName = $inputObj.Name | |
RealName = $inputObj.Host.RealName.ToLower() | |
Disabled = $inputObj.IsDisabled | |
Status = $hostAlive | |
IP = $pinginfo.Address | |
Responce = $pinginfo.RoundtripTime | |
ReadData = [Decimal]0.00 | |
WriteData = [Decimal]0.00 | |
UsageCount = 0 | |
ProxiesInSessions = $($totalObjInJob*2) | |
} | |
return $vPCFuncObject | |
} | |
function Get-vPCProxyName {param ([String]$title) | |
$titleAry = @($title.Split()) | |
$ai = 3 | |
$bi = $titleAry.count – 1 | |
while ($ai -ne $bi) { | |
$proxyString = $proxyString + " " + $titleAry[$ai] | |
$ai ++ | |
} | |
return $proxyString.Trim() | |
} | |
function Get-vPCProxyRole {param ([String]$title) | |
$titleAry = @($title.Split()) | |
$roleString = $titleAry[1] | |
return $roleString | |
} | |
Get-VBRViProxy | %{$vPCObjAry = $vPCObjAry + $(Build-vPCObj $_)} | |
} | |
Process { | |
if ($Name -ne $null) { | |
$output = $vPCObjAry | ?{$Name -like $_.ProxyName} | |
} | |
else { | |
$output = $vPCObjAry | |
} | |
} | |
End { | |
$output | |
} | |
} | |
function Get-vPCRepoInfo { | |
[CmdletBinding()] | |
param ( | |
[Parameter(Position=0, ValueFromPipeline=$true)] | |
[PSObject[]]$Repository | |
) | |
Begin { | |
$outputAry = @() | |
[Reflection.Assembly]::LoadFile($veeamDllPath) | Out-Null | |
function Build-Object {param($name, $path, $free, $total) | |
$repoObj = New-Object -TypeName PSObject -Property @{ | |
Target = $name | |
Storepath = $path | |
StorageFree = [Math]::Round([Decimal]$free/1GB,2) | |
StorageTotal = [Math]::Round([Decimal]$total/1GB,2) | |
FreePercentage = [Math]::Round(($free/$total)*100) | |
} | |
return $repoObj | Select Target, Storepath, StorageFree, StorageTotal, FreePercentage | |
} | |
} | |
Process { | |
foreach ($r in $Repository) { | |
if ($r.GetType().Name -eq [String]) { | |
$r = Get-VBRBackupRepository -Name $r | |
} | |
if ($r.Type -eq "WinLocal") { | |
$Server = $r.GetHost() | |
$FileCommander = [Veeam.Backup.Core.CRemoteWinFileCommander]::Create($Server.Info) | |
$storage = $FileCommander.GetDrives([ref]$null) | ?{$_.Name -eq $r.Path.Substring(0,3)} | |
$outputObj = Build-Object $r.Name $r.Path $storage.FreeSpace $storage.TotalSpace | |
} | |
elseif ($r.Type -eq "LinuxLocal") { | |
$Server = $r.GetHost() | |
$FileCommander = new-object Veeam.Backup.Core.CSshFileCommander $server.info | |
$storage = $FileCommander.FindDirInfo($r.Path) | |
$outputObj = Build-Object $r.Name $r.Path $storage.FreeSpace $storage.TotalSize | |
} | |
elseif ($r.Type -eq "CifsShare") { | |
$fso = New-Object -Com Scripting.FileSystemObject | |
$storage = $fso.GetDrive($r.Path) | |
$outputObj = Build-Object $r.Name $r.Path $storage.AvailableSpace $storage.TotalSize | |
} | |
$outputAry = $outputAry + $outputObj | |
} | |
} | |
End { | |
$outputAry | |
} | |
} | |
function Get-vPCReplicaTarget { | |
[CmdletBinding()] | |
param( | |
[Parameter(ValueFromPipeline=$true)] | |
[PSObject[]]$InputObj | |
) | |
BEGIN { | |
$outputAry = @() | |
$dsAry = @() | |
if (($Name -ne $null) -and ($InputObj -eq $null)) { | |
$InputObj = Get-VBRJob -Name $Name | |
} | |
} | |
PROCESS { | |
foreach ($obj in $InputObj) { | |
if (($dsAry -contains $obj.ViReplicaTargetOptions.DatastoreName) -eq $false) { | |
$esxi = $obj.GetTargetHost() | |
$dtstr = $esxi | Find-VBRViDatastore -Name $obj.ViReplicaTargetOptions.DatastoreName | |
$objoutput = New-Object -TypeName PSObject -Property @{ | |
Target = $esxi.Name | |
Datastore = $obj.ViReplicaTargetOptions.DatastoreName | |
StorageFree = [Math]::Round([Decimal]$dtstr.FreeSpace/1GB,2) | |
StorageTotal = [Math]::Round([Decimal]$dtstr.Capacity/1GB,2) | |
FreePercentage = [Math]::Round(($dtstr.FreeSpace/$dtstr.Capacity)*100) | |
} | |
$dsAry = $dsAry + $obj.ViReplicaTargetOptions.DatastoreName | |
$outputAry = $outputAry + $objoutput | |
} | |
else { | |
return | |
} | |
} | |
} | |
END { | |
$outputAry | Select Target, Datastore, StorageFree, StorageTotal, FreePercentage | |
} | |
} | |
function Get-VeeamVersion { | |
$veeamExe = Get-Item $veeamExePath | |
$VeeamVersion = $veeamExe.VersionInfo.ProductVersion | |
Return $VeeamVersion | |
} | |
function Get-VeeamSupportDate { | |
#Get version and license info | |
$regBinary = (Get-Item 'HKLM:\SOFTWARE\Veeam\Veeam Backup and Replication\license').GetValue('Lic1') | |
$veeamLicInfo = [string]::Join($null, ($regBinary | % { [char][int]$_; })) | |
if($script:VeeamVersion -like "6*"){ | |
$pattern = "Expiration date\=\d{1,2}\/\d{1,2}\/\d{1,4}" | |
} | |
elseif($script:VeeamVersion -like "5*"){ | |
$pattern = "EXPIRATION DATE\=\d{1,2}\/\d{1,2}\/\d{1,4}" | |
} | |
elseif($script:VeeamVersion -like "7*"){ | |
$pattern = "expiration date\=\d{1,2}\/\d{1,2}\/\d{1,4}" | |
} | |
# Convert Binary key | |
if($script:VeeamVersion -like "5*" -OR $script:VeeamVersion -like "6*" -OR $script:VeeamVersion -like "7*"){ | |
$expirationDate = [regex]::matches($VeeamLicInfo, $pattern)[0].Value.Split("=")[1] | |
$datearray = $expirationDate -split '/' | |
$datearray = $datearray[1],$datearray[0],$datearray[2] | |
$expirationDate = $datearray -join '/' | |
$totalDaysLeft = ((Get-Date $expirationDate) – (get-date)).Totaldays.toString().split(",")[0] | |
$totalDaysLeft = [int]$totalDaysLeft | |
$objoutput = New-Object -TypeName PSObject -Property @{ | |
ExpDate = $expirationDate | |
DaysRemain = $totalDaysLeft | |
} | |
$objoutput | |
} | |
else{ | |
$objoutput = New-Object -TypeName PSObject -Property @{ | |
ExpDate = "Failed" | |
DaysRemain = "Failed" | |
} | |
$objoutput | |
} | |
} | |
function Get-VeeamServers { | |
$vservers=@{} | |
$outputAry = @() | |
$vservers.add($($script:vbrserver.realname),"VBRServer") | |
foreach ($srv in $script:viProxyList) { | |
If (!$vservers.ContainsKey($srv.Host.Realname)) { | |
$vservers.Add($srv.Host.Realname,"ProxyServer") | |
} | |
} | |
foreach ($srv in $script:repoList) { | |
If (!$vservers.ContainsKey($srv.gethost().Realname)) { | |
$vservers.Add($srv.gethost().Realname,"RepoServer") | |
} | |
} | |
$vservers = $vservers.GetEnumerator() | Sort-Object Name | |
foreach ($vserver in $vservers) { | |
$outputAry += $vserver.Name | |
} | |
return $outputAry | |
} | |
function Get-VeeamServices { | |
param ( | |
[PSObject]$inputObj) | |
$outputAry = @() | |
foreach ($obj in $InputObj) { | |
$output = Get-Service -computername $obj -Name "*Veeam*" -exclude "SQLAgent*" | | |
Select @{Name="Server Name"; Expression = {$obj}}, @{Name="Service Name"; Expression = {$_.DisplayName}}, Status | |
$outputAry = $outputAry + $output | |
} | |
$outputAry | |
} | |
function Get-VMsMissingBackup { | |
param ( | |
[String]$vcenter) | |
$outputary = @() | |
$vcenterobj = Get-VBRServer -Name $vcenter | |
$vmobjs = Find-VBRObject -Server $vcenterobj | Where-Object {$_.Type -eq "VirtualMachine" -and $_.VMFolderName -notlike $script:folderExclude} | |
$jobobjids = [Veeam.Backup.Core.CHierarchyObj]::GetObjectsOnHost($vcenterobj.id) | Where-Object {$_.GetItem().Type -eq "Vm"} | |
# Convert exclusion list to simple regular expression | |
$excludevms_regex = (‘(?i)^(‘ + (($script:excludevms | ForEach {[regex]::escape($_)}) –join “|”) + ‘)$’) -replace "\\\*", ".*" | |
foreach ($vm in $vmobjs) { | |
$jobobjid = ($jobobjids | Where-Object {$_.ObjectId -eq $vm.Id}).Id | |
if (!$jobobjid) { | |
$jobobjid = $vm.FindParent("Datacenter").Id + "\" + $vm.Id | |
} | |
$vm | Add-Member -MemberType NoteProperty "JobObjId" -Value $jobobjid | |
} | |
# Get a list of all VMs from vCenter and add to hash table, assume Unprotected | |
$vms=@{} | |
foreach ($vm in ($vmobjs | where {$_.Name -notmatch $excludevms_regex})) { | |
if(!$vms.ContainsKey($vm.JobObjId)) { | |
$vms.Add($vm.JobObjId, @("!", [string]$vm.GetParent("Datacenter"), $vm.Name)) | |
} | |
} | |
# Find all backup job sessions that have ended in the last x hours | |
$vbrjobs = Get-VBRJob | Where-Object {$_.JobType -eq "Backup"} | |
$vbrsessions = Get-VBRBackupSession | Where-Object {$_.JobType -eq "Backup" -and $_.EndTime -ge (Get-Date).addhours(-$script:HourstoCheck)} | |
# Find all successfully backed up VMs in selected sessions (i.e. VMs not ending in failure) and update status to "Protected" | |
if ($vbrsessions) { | |
foreach ($session in $vbrsessions) { | |
foreach ($vm in ($session.gettasksessions() | Where-Object {$_.Status -ne "Failed"} | ForEach-Object { $_ })) { | |
if($vms.ContainsKey($vm.Info.ObjectId)) { | |
$vms[$vm.Info.ObjectId][0]=$session.JobName | |
} | |
} | |
} | |
} | |
$vms = $vms.GetEnumerator() | Sort-Object Value | |
foreach ($vm in $vms) { | |
if ($vm.Value[0] -eq "!") { | |
$objoutput = New-Object -TypeName PSObject -Property @{ | |
Datacenter = $vm.Value[1] | |
Name = $vm.Value[2] | |
} | |
$outputAry += $objoutput | |
} | |
} | |
$outputAry | Select Datacenter, Name | Sort Name | |
} | |
#endregion | |
#region Report | |
# Get Veeam Version | |
$VeeamVersion = Get-VeeamVersion | |
# HTML Stuff | |
$headerObj = @" | |
<html> | |
<head> | |
<title>$rptTitle</title> | |
<style> | |
body {font-family: Tahoma; background-color:#fff;width: 1024px;} | |
table {font-family: Tahoma;width: 1024px;font-size: 12px;border-collapse:collapse;} | |
<!– table tr:nth-child(odd) td {background: #e2e2e2;} –> | |
th {background-color: #cccc99;border: 1px solid #a7a9ac;border-bottom: none;} | |
td {background-color: #ffffff;border: 1px solid #a7a9ac;padding: 2px 3px 2px 3px;vertical-align: top;} | |
</style> | |
</head> | |
"@ | |
$bodyTop = @" | |
<body> | |
<table cellspacing="0" cellpadding="0"> | |
<tr> | |
<td style="width: 80%;height: 45px;border: none;background-color: #003366;color: White;font-size: 24px;vertical-align: bottom;padding: 0px 0px 0px 15px;">$rptTitle</td> | |
<td style="width: 30%;height: 45px;border: none;background-color: #003366;color: White;font-size: 12px;vertical-align:text-top;text-align:right;padding: 2px 3px 2px 3px;">v$vPCARversion<br>Veeam v$VeeamVersion</td> | |
</tr> | |
<tr> | |
<td style="width: 80%;height: 35px;border: none;background-color: #003366;color: White;font-size: 10px;vertical-align: bottom;padding: 0px 0px 2px 3px;">Report generated: $(Get-Date -format g)</font></td> | |
<td style="width: 30%;height: 35px;border: none;background-color: #003366;color: White;font-size: 10px;vertical-align:bottom;text-align:right;padding: 2px 3px 2px 3px;">Based on:<br><a href="http://www.vpowercli.co.uk/2012/01/23/vpowercli-v6-army-report/" target="_blank"><font color="White">vPowerCLI v6 Army Report</font></a></td> | |
</tr> | |
</table> | |
"@ | |
$subHead01 = @" | |
<table> | |
<tr> | |
<td style="height: 35px;background-color: #eeeeee;color: #003366;font-size: 16px;font-weight: bold;vertical-align: middle;padding: 5px 0 0 15px;border-top: none;border-bottom: none;"> | |
"@ | |
$subHead02 = @" | |
</td> | |
</tr> | |
</table> | |
"@ | |
$footerObj = @" | |
</body> | |
</html> | |
"@ | |
If ($VeeamVersion -lt 7) { | |
Write-Host "Script requires VBR v7 or greater" | |
exit | |
} | |
# Get Summary Info | |
$vbrMasterHash = @{"Coordinator" = "$((gc env:computername).ToLower())"; "Failed" = $failedSessions.Count; "Sessions" = $totalSessions.Count; | |
"Read" = $totalRead; "Transferred" = $totalXfer; "Successfull" = $succesSessions.Count; "Warning" = $warningSessions.Count; | |
"Fails" = $failsSessions.Count; "Running" = $runningSessions.Count;} | |
$vbrMasterObj = New-Object -TypeName PSObject -Property $vbrMasterHash | |
$bodyMasterT = $vbrMasterObj | Select Coordinator, @{Name="Job Runs"; Expression = {$_.Sessions}}, | |
@{Name="Read (GB)"; Expression = {$_.Read}}, @{Name="Transferred (GB)"; Expression = {$_.Transferred}}, | |
@{Name="Running"; Expression = {$_.Running}}, @{Name="Successfull"; Expression = {$_.Successfull}}, | |
@{Name="Warnings"; Expression = {$_.Warning}}, @{Name="Failures"; Expression = {$_.Fails}}, | |
@{Name="Failed"; Expression = {$_.Failed}} | ConvertTo-HTML -Fragment | |
# Get VMs Missing Backups | |
$bodyMissing = $null | |
If ($showMissing) { | |
$missingVMs = @() | |
foreach ($vcenter in $vcenters) { | |
$missing = Get-VMsMissingBackup $vcenter | Select Datacenter, Name | |
$missingVMs += $missing | |
} | |
If ($missingVMs -ne $null) { | |
$missingVMs = $missingVMs | Sort Datacenter, Name | ConvertTo-HTML -Fragment | |
$bodyMissing = $subHead01 + "VMs with no successful backups" + $subHead02 + $missingVMs | |
} | |
} | |
# Get Running Jobs | |
$bodyrLines = $null | |
if ($rlines -eq $true) { | |
if ($runningSessions.count -gt 0) { | |
$bodyrLines = $runningSessions | Sort Creationtime | Select @{Name="Job Name"; Expression = {$_.Name}}, | |
@{Name="Start Date"; Expression = {$_.Progress.StartTime.ToShortDateString()}}, | |
@{Name="Start Time"; Expression = {$_.Progress.StartTime.ToShortTimeString()}}, | |
@{Name="Duration"; Expression = {Get-Date "$($_.Progress.Duration)" -f HH:mm:ss}}, | |
@{Name="Read (GB)"; Expression = {[Math]::Round([Decimal]$_.Progress.ReadSize/1GB, 2)}}, | |
@{Name="Write (GB)"; Expression = {[Math]::Round([Decimal]$_.Progress.TransferedSize/1GB, 2)}} | ConvertTo-HTML -Fragment | |
$bodyrLines = $subHead01 + "Running Jobs" + $subHead02 + $bodyrLines | |
} | |
} | |
# Get Jobs with Failures or Warnings | |
$bodyjLines = $null | |
if ($jlines -eq $true) { | |
$counter = @($seshList | ?{($_.Result -eq "Warning") -or ($_.Result -eq "Failed")}) | |
if ($counter.count -gt 0) { | |
$bodyjLines = $seshList | ?{($_.Result -eq "Warning") -or ($_.Result -eq "Failed")} | Sort Creationtime | Select @{Name="Job Name"; Expression = {$_.Name}}, | |
@{Name="Start Date"; Expression = {$_.Progress.StartTime.ToShortDateString()}}, | |
@{Name="Start Time"; Expression = {$_.Progress.StartTime.ToShortTimeString()}}, | |
@{Name="Stop Time"; Expression = {$_.Progress.StopTime.ToShortTimeString()}}, | |
@{Name="Details"; Expression = {($_.GetDetails()).Replace("<br />"," – ")}},Result | ConvertTo-HTML -Fragment | |
$bodyjLines = $subHead01 + "Sessions with Warnings or Failures" + $subHead02 + $bodyjLines | |
} | |
} | |
# Get Proxy Info | |
$bodyProxy = $null | |
if ($viProxyList -ne $null -And $seshList -ne $null) { | |
$bodyProxy = Get-vPCProxyInfo -Sessions $seshList | Select @{Name="Proxy Host"; Expression = {$_.RealName}}, | |
Disabled, @{Name="IP Address"; Expression = {$_.IP}}, @{Name="RT (ms)"; Expression = {$_.Responce}}, Status | | |
Sort "Proxy Host" | ConvertTo-HTML -Fragment | |
$bodyProxy = $subHead01 + "Proxy Details" + $subHead02 + $bodyProxy | |
} | |
# Get Repository Info | |
$bodyRepo = $null | |
if ($repoList -ne $null) { | |
$bodyRepo = $repoList | Get-vPCRepoInfo | Select @{Name="Repository Name"; Expression = {$_.Target}}, | |
@{Name="Path"; Expression = {$_.Storepath}}, @{Name="Free (GB)"; Expression = {$_.StorageFree}}, | |
@{Name="Total (GB)"; Expression = {$_.StorageTotal}}, @{Name="Free (%)"; Expression = {$_.FreePercentage}}, | |
@{Name="Status"; Expression = {If ($_.FreePercentage -lt $repoCritical) {"Critical"} ElseIf ($_.FreePercentage -lt $repoWarn) {"Warning"} Else {"OK"}}} | ` | |
Sort "Repository Name" | ConvertTo-HTML -Fragment | |
$bodyRepo = $subHead01 + "Repository Details" + $subHead02 + $bodyRepo | |
} | |
# Get Replica Target Info | |
$bodyReplica = $null | |
if ($repList -ne $null) { | |
$bodyReplica = $repList | Get-vPCReplicaTarget | Select @{Name="Replica Target"; Expression = {$_.Target}}, Datastore, | |
@{Name="Free (GB)"; Expression = {$_.StorageFree}}, @{Name="Total (GB)"; Expression = {$_.StorageTotal}}, | |
@{Name="Free (%)"; Expression = {$_.FreePercentage}}, | |
@{Name="Status"; Expression = {If ($_.FreePercentage -lt $replicaCritical) {"Critical"} ElseIf ($_.FreePercentage -lt $replicaWarn) {"Warning"} Else {"OK"}}} | ` | |
Sort "Replica Target" | ConvertTo-HTML -Fragment | |
$bodyReplica = $subHead01 + "Replica Details" + $subHead02 + $bodyReplica | |
} | |
# Get Veeam Services Info | |
$bodyServices = Get-VeeamServers | |
$bodyServices = Get-VeeamServices $bodyServices | |
If ($runningSvc -ne $true) {$bodyServices = $bodyServices | ?{$_.Status -ne "Running"}} | |
If ($bodyServices -ne $null) { | |
$bodyServices = $bodyServices | Select "Server Name", "Service Name", Status | Sort "Server Name", "Service Name" | ConvertTo-HTML -Fragment | |
$bodyServices = $subHead01 + "Services" + $subHead02 + $bodyServices | |
} | |
# Get License Info | |
$bodyLicense = Get-VeeamSupportDate | Select @{Name="Expiry Date"; Expression = {$_.ExpDate}}, @{Name="Days Remaining"; Expression = {$_.DaysRemain}}, ` | |
@{Name="Status"; Expression = {If ($_.DaysRemain -lt $licenseCritical) {"Critical"} ElseIf ($_.DaysRemain -lt $licenseWarn) {"Warning"} Else {"OK"}}} | ` | |
ConvertTo-HTML -Fragment | |
$bodyLicense = $subHead01 + "License/Support Renewal Date" + $subHead02 + $bodyLicense | |
# Combine HTML Output | |
$htmlOutput = $headerObj + $bodyTop + $bodyMasterT + $bodyMissing + $bodyrLines + $bodyjLines + $bodyRepo + $bodyProxy + $bodyReplica + $bodyServices + $bodyLicense + $footerObj | |
# Add color to output depending on results | |
$htmlOutput = $htmlOutput.Replace("<td>Running<","<td style=""background-color: Green;color: White;"">Running<") | |
$htmlOutput = $htmlOutput.Replace("<td>OK<","<td style=""background-color: Green;color: White;"">OK<") | |
$htmlOutput = $htmlOutput.Replace("<td>Alive<","<td style=""background-color: Green;color: White;"">Alive<") | |
$htmlOutput = $htmlOutput.Replace("<td>Warning<","<td style=""background-color: Yellow;"">Warning<") | |
$htmlOutput = $htmlOutput.Replace("<td>Stopped<","<td style=""background-color: Red;color: White;"">Stopped<") | |
$htmlOutput = $htmlOutput.Replace("<td>Failed<","<td style=""background-color: Red;color: White;"">Failed<") | |
$htmlOutput = $htmlOutput.Replace("<td>Critical<","<td style=""background-color: Red;color: White;"">Critical<") | |
$htmlOutput = $htmlOutput.Replace("<td>Dead<","<td style=""background-color: Red;color: White;"">Dead<") | |
$htmlOutput = $htmlOutput.Replace("<th>Datacenter</th><th>","<th style=""background-color: Red;"">Datacenter<th style=""background-color: Red;"">") | |
#endregion | |
#region Output | |
if ($sendEmail) { | |
$emailSubject = $rptTitle | |
$smtp = New-Object System.Net.Mail.SmtpClient $emailHost | |
$smtp.Credentials = New-Object System.Net.NetworkCredential($emailUser, $emailPass); | |
$msg = New-Object System.Net.Mail.MailMessage($emailFrom, $emailTo) | |
$msg.Subject = $emailSubject | |
If ($emailAttach) { | |
$body = "Veeam Report Attached" | |
$msg.Body = $body | |
$tempfile = "$env:TEMP\$rptTitle.htm" | |
$htmlOutput | Out-File $tempfile | |
$attachment = new-object System.Net.Mail.Attachment $tempfile | |
$msg.Attachments.Add($attachment) | |
} Else { | |
$body = $htmlOutput | |
$msg.Body = $body | |
$msg.isBodyhtml = $true | |
} | |
$smtp.send($msg) | |
If ($emailAttach) { | |
$attachment.dispose() | |
Remove-Item $tempfile | |
} | |
} else { | |
$htmlOutput | Out-File $file | |
Invoke-Expression $file | |
} | |
#endregion |
Update 03/25/2014 – Version 1.1.4
- Misc tweaks/bug fixes
- Reconfigured HTML a bit to help with certain email clients
- Added cell coloring to highlight status
- Added $rptTitle variable to hold report title
- Added ability to send report via email as attachment
Your script doesn’t work for me, it creates a wrong HTML page without correct tags like: style body …
Hi Ajeje
The code was chewed up a bit and some of the html markup was stripped. I’ve switched how the code is displayed and should it be easier to work with now.
Let me know if you still have issues.
–shawn
Whould be nice to have a link with the full powershell script.
Whishlist:
– Able to set a title from config variable
– Able to have a different e-mail subject if there are jobs with Warning/Errors. So it is possible to filter mails on the client side…
– HTML colors according to success, warning, errors
– Able to send e-mail to different recpient according to the results of the jobs. Ex: If success: mail1; if warning: mail1,mail2; if error: mail1,mail2,supervisor-mail
Ajeje – You can hit a link to the Gist at the bottom of the script – this makes it easier to download the entire script. Unfortunately, WordPress does not allow for file hosting (only images), I think a gist is the next best thing.
I’ve also added a few new tweaks including a title variable and HTML coloring of some of the cells to highlight status.
Let me know what you think
–shawn
Hello I am very very new to power shell. I have saved your code as .pS1 and when I run it using power shell on the Veeam server I get bunch of errors and the an html out put showing the version a job table with no information in it.
Is all the red in your script suppose to be replace with current relevant information- I am need of guidance thanks.
Hello,
It sounds like you might not have the Veeam PowerShell snapin installed. More info can be found here – http://www.veeam.com/kb1489
The user variables section (lines 3 – 54) should be updated with your relevant information.
Hope this helps
–shawn
Hello Shawn, thank you for you response. I have installed the Add-in and adjusted the script from 3-54 and I am getting all information except for VM with no successful backups section ( is this section for identifying which machine in on ESXi are not part of any backup job?) -I really need this feature since we have over 200 VM in our environment and I don’t know what is not added to Veeam jobs.
Thank you for all your help.
MK
The missing VM section is highly dependent on ensuring your vcenter name listed on line 16 is exactly how it is shown within Veeam (Backup Infrastructure > Managed Servers > VMware vSphere > vCenter Servers)
I will check and get back to you. I appreciate you getting back to me so quickly.
Hello Shaw,sorry to bother you again please I am I have confirmed that I am using the VMware server same as Veeam software. When rung the script on the Veeam server I get the following error and then an HTML with only:
Repository Details
Repository Name
Proxy Details
License/Support Renewal Date
AND THE FOLLOWING ERROR:
Find-VBRObject : Cannot validate argument on parameter ‘Server’. The argument i
s null. Supply a non-null argument and try the command again.
At C:\Users\administrator\Desktop\Veeam Report.ps1:443 char:34
+ $vmobjs = Find-VBRObject -Server <<<< $vcenterobj | Where-Object {$_.Typ
e -eq "VirtualMachine" -and $_.VMFolderName -notlike $script:folderExclude}
+ CategoryInfo : InvalidData: (:) [Find-VBRObject], ParameterBind
ingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Veeam.Backup.Po
werShell.Command.FindVBRObject
Cannot convert argument "0", with value: "", for "GetObjectsOnHost" to type "Sy
stem.Guid": "Cannot convert null to type "System.Guid"."
At C:\Users\administrator\Desktop\Veeam Report.ps1:444 char:66
+ $jobobjids = [Veeam.Backup.Core.CHierarchyObj]::GetObjectsOnHost <<<< ($v
centerobj.id) | Where-Object {$_.GetItem().Type -eq "Vm"}
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
You cannot call a method on a null-valued expression.
At C:\Users\administrator\Desktop\p\Veeam Report.ps1:453 char:30
+ $jobobjid = $vm.FindParent <<<< ("Datacenter").Id + "\" + $vm.Id
+ CategoryInfo : InvalidOperation: (FindParent:String) [], Runtim
eException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Add-Member : Cannot bind argument to parameter 'InputObject' because it is null
.
At CC:\Users\administrator\Desktop\\Veeam Report.ps1:455 char:19
+ $vm | Add-Member <<<< -MemberType NoteProperty "JobObjId" -Value $jo
bobjid
+ CategoryInfo : InvalidData: (:) [Add-Member], ParameterBindingV
alidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,M
icrosoft.PowerShell.Commands.AddMemberCommand
Cannot index into a null array.
I have one question , if i more than one veeam backup server how script knows about ◦VMs with no successful backups for that particular Server .. or I will query vcenter server server and give me list of all VMS which are not included for particular veeam backup server..
Hi Hem,
Unfortunately this is going to be a limitation of the script as it assumes one backup server is protecting the entire vCenter environment (or multiple vCenters).
–shawn
Thanks Shawn! Any way to exclude Backup Copy Jobs from the job counts at the top of the email?
I think I figured it out. I modified this line in the script:
$seshList = $allSesh | ?{($_.CreationTime -ge (Get-Date).AddHours(-$HourstoCheck)) -and ($_.State -ne “Working”) -and ($_.JobType -ne “BackupSync”) -and ($_.Name -ne “Lab Backup”)}
I added the -and ($_.JobType -ne “BackupSync”) -and ($_.Name -ne “Lab Backup”). This excludes Backup Copy Jobs and a specific job I have with the name Lab Backup. Works great now!
That should do the trick.
Glad you find the script useful!
Hi Shawn
Great script.
For the life of me I can’t get it to email multiple recipients have tried @(“recipient1@domain”, “recipient2@domain”) does not seem to like it. Will only email the last recipient in the list. Any ideas ?
Cheers
Surely can be done, try this:
$emailTo = “recipient1@mydomain.com,recipient2@mydomain.com”
Hope this helps!
Worked !!! Thanks again. I think I tried every other option bar that one.
I am getting also an error. Perhaps you could check.
#region Report
# Get Veeam Version
$VeeamVersion = Get-VeeamVersion
# HTML Stuff
$headerObj = @”” im Ausdruck oder in der Anweisung.
Bei C:\Users\USERNAME\Desktop\MyVeeamReport.ps1:503 Zeichen:16
+ $excludevms_re <<<< gex = (â?~(?i)^(â?~ + (($script:excludevms | ForEach {[regex]::escape($_)}) â?"join â?o|â??)
+ â?~)$â?T) -replace "\\\*", ".*"
+ CategoryInfo : ParserError: (â?"join â?o|â??…$headerObj = @":String) [], ParseException
+ FullyQualifiedErrorId : UnexpectedToken
Never mind. I found it.
Wrong charset -> $excludevms_regex = (‘(?i)^(‘ + (($script:excludevms | ForEach {[regex]::escape($_)}) –join “|â€) + ‘)$’) -replace “\\\*”, “.*”
Hello again,
Another issue:
Get-Date : Cannot bind parameter ‘Date’. Cannot convert value “10/13/2014” to type “System.DateTime”. Error: “String was not recognized as a valid DateTime.”
At C:\Users\NAME\Desktop\VeeamReport.ps1:386 char:30
+ $totalDaysLeft = ((Get-Date <<<< $expirationDate) – (get-date)).Totaldays.toString().split(",")[0]
+ CategoryInfo : InvalidArgument: (:) [Get-Date], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetDateCommand
Tried to figure it out myself. But without success.
Thanks
Quick guess has me thinking your date format is different than mine (USA vs World…)
Try swapping the order in line 384
$datearray = $datearray[1],$datearray[0],$datearray[2]
change to
$datearray = $datearray[0],$datearray[1],$datearray[2]
This should switch the expiration date retrieved from month/day/year to day/month/year
I haven’t tested the script at all with different locales…this seems to be the issues you are encountering.
HTH
Hi. Thank you for this nice piece of code!
BTW, I made some modifications to print the list of successful backups (I like having a list of what really happened, so I can be sure that no VM has been forgotten in the batch): let me know if you want me to send my version.
BR,
Georges
That’s a great addition. I like the idea of being able to toggle the option on or off as it would get cumbersome in large environments. You can send to smasterson via gmail if you’d like.
Thanks!
Done 😉
Very nice, how come the proxy utilization was removed?
Glad you like 🙂
I don’t recall exactly what the issue was but v7 had broken the proxy utilization. I should prolly swing back around and check it out as the functionality was nice.
Nice repport script. question, is it possible to extract the vm’s from a job?
I mean we have all the vm’s now in a folder that Veeam takes backup and inside of thet folder is all the vm’s that i need to get the times.
Pingback: My Veeam Report v1.2 | Shawn Masterson's Blog
Pingback: My Veeam Report v1.3 with VBR v8 Support | Shawn Masterson's Blog
Hi,
Thanks for this, I really love this script.
I have just tried it on veeam B&R 8 Patch 1 with VMware 5.1 and see a few errors.
Can you please take a look?
WARNING: This cmdlet is obsolete, use Find-VBRViEntity instead
Method invocation failed because [Veeam.Backup.Core.CHierarchyObj] does not contain a method named ‘GetItem’.
At E:\MyVeeamReport.ps1:444 char:99
+ … Where-Object {$_.GetItem().Type -eq “Vm”}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Unable to find type [Veeam.Backup.Core.CRemoteWinFileCommander]. Make sure that the assembly that contains this type is loaded.
At E:\MyVeeamReport.ps1:297 char:33
+ $FileCommander = [Veeam.Backup.Core.CRemoteWinFi …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (Veeam.Backup.Co…inFileCommander:TypeName) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound
You cannot call a method on a null-valued expression.
At E:\MyVeeamReport.ps1:298 char:33
+ $storage = $FileCommander.GetDrives([ref]$null) …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Attempted to divide by zero.
At E:\MyVeeamReport.ps1:280 char:25
+ $repoObj = New-Object -TypeName PSObject -Property @{
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
regards,
Martijn
Hi Martijn
For the VBR v8 version of the script, check here:
http://blog.smasterson.com/2014/12/18/my-veeam-report-v1-3-with-vbr-v8-support/
Unexpected token ‘â?”join â?o|â??) + â?~)$â?T) -replace “\\\*”, “.*”
foreach ($vm in $vmobjs) {
$jobobjid = ($jobobjids | Where-Object {$_.ObjectId -eq $vm.Id})
if (!$jobobjid) {
$jobobjid = $vm.FindParent(“Datacenter”).Id + “\” + $vm.Id
all i did was replace the server and paths as required….any ideas?
Hi Rob
Did you happen to use the ‘raw view’ or download option on the Gist? For some reason they are both changing characters on line 461. Try copying from the Gist window itself.
line 461 (ish depending on version) should read:
$excludevms_regex = (‘(?i)^(‘ + (($script:excludevms | ForEach {[regex]::escape($_)}) –join “|”) + ‘)$’) -replace “\\\*”, “.*”
thanks, that was exactly the issue. I’m fairly new to powershell scripting, is there an easy way to only collect the last session for failed jobs instead of seeing the failure plus all 3 retries? We have over 400 vm’s being backed up by about 100 jobs, and 20 of them were failing…it was pretty impossible to read :/
Hey Roy
The ‘only show last session per job’ has come up a few times now – I’ll see if I can incorporate it in the next version.
Thanks!
I came looking for some Veeam V8 Updates and found this original post (and your V8 updates).
I think it’s great that you were able to get started from some my scripts and I’m able to streamline some updates based on your work 🙂
Thanks for the credit and link – I’ll ensure to do the same.
TheAgreeableCow
Mudos!
Hi guys,
always appears the errormessage
Attempted to divide by zero.
At C:\Batch\Veeam\VeeamReport\veeamreport.ps1:293 char:25
+ $repoObj = New-Object -TypeName PSObject -Property @{
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
Thanks
Michael
Hi Michael
What version of the report are you running?
What version of VBR are you running?
Hi
I have running the latest version of Reports (1.3) and the latest version of VBR (8.0.0.2021)
Thanks and Greetings
Michael
It appears as though the script is unable to determine the free space on your repo(s).
What types of repositories are you running?
Is there any info returned in the repo section? If so, are any of your repo’s missing?
Hi,
OK. Ich habe den Fehler gefunden. Es gab noch alte repos welche nicht mehr existieren.
Thanke für die Hilfe.
Grüße
Michael
And now in English 🙂
Hi,
OK. I have found the error. There were old repos which no longer exist.
Thanke for help.
regards
Michael
Hi,
New questions or suggestions :-):
1. Is it possible to exclude whole VmWare Date Center?
We have a vCenter with several small Datacenter (ESXi hosts max. 2) running in the branch office. This will not backup at the central site.
2. Is it possible to exclude multiple folders?
3. Is it possible to exclude certain backup jobs?
We have several daily jobs with certain virtual machines and several weekly jobs with certain virtual machines.
In the daily report the machines are always displayed under “VMs with no successful backups”, which are only backed up weekly.
If I can exclude backup jobs, then I can work with two reports. A daily and a weekly with different settings.
Thanke very much and greetings
Michael
Thanks a bunch for the feedback – always welcomed.
I’m in process of polishing v1.4 and went ahead and added suggestions #1 and #2.
Regarding #3 – it could get a bit hairy. I think you hit it on the head with having multiple reports. Configure one for daily and another for weekly with each having different VM/Folder/DC exclusions.
Hi,
sehr sehr schön Skript
Vielen vielen Danke für die Änderungen
Beste Grüße aus Südtirol
Michael
Hi,
very very nice script
Many many thanks for the changes
Best regards from South Tyrol
Michael
Hello Shawn!
Thank you so much for the script. I am learning how to use power shell to create a report that says what the job is, what vmdk was backed up, if the job was successful or not, and what is the repository. This has been a struggle for me. I tried your script and i’m not sure if I plugged in my specific information correctly. I saw that another person got the same error as me and I’m not clear on the fix for:
Warning: This cmdlet is Obsolete, use Find-VBRiEntity instead.
Hi Chanda – that warning can be disregarded, it is just telling us that the command may not exist in the future, but works fine for now.
Thank for replying. Unfortunately, I don’t see an output of the report. I thought it was incomplete.
Are there any errors generated or other odd output in the console?
Be sure you are running the latest version – currently 1.2 for VBR v7 and 1.4 for VBR v8.
Could also try setting to save to file as opposed to send email.
I’m interested in getting a simple (I think) tabular report of the Veeam Session Report, preferably in a CSV format so that I can then import to Excel for graphing trends. Towards that end, should I just be able to trim everything but the “Job/Session details over period of time (12,24,Week,Month)”?
I’m very new to PS scripts, and have been mostly successful in modding ’em for my needs, but I’m under a time constraint with this endeavor, so whatever time you could spare to assist would be very much appreciated!
This is a great powershell report!!!
A couple of minor fixes i’d like to see:
1) Use your ‘exclude list’ within the Successful Sessions section too.
2) Allow custom colour codes/html headers for SUCCESS/FAILED/Warning/Error/Other; giving the administrator more control – it’s a little difficult to find/change without affecting a large block of the report
3) In Replica Details, please include the VM name
4) In Successful Sessions, please include the Job Type (backup/replication) AND sort by type then Job Name (basically group Backup Jobs in order; then Recover jobs in order and finally Replication jobs in order).
Simon
Hi I am trying to run 9.0.3 first time. After making necessary changes when try to test the script it fails. It gives me error on shell..
PS D:\Veeam_Report> D:\Veeam_Report\MyVeeamReport.ps1
Get-VBRServerSession : Access to the registry key ‘HKEY_LOCAL_MACHINE\SOFTWARE\Veeam\Veeam Backup and Replication’ is denied.
At D:\Veeam_Report\MyVeeamReport.ps1:544 char:20
+ $OpenConnection = (Get-VBRServerSession).Server
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException
Disconnect-VBRServer : Access to the registry key ‘HKEY_LOCAL_MACHINE\SOFTWARE\Veeam\Veeam Backup and Replication’ is denied.
At D:\Veeam_Report\MyVeeamReport.ps1:546 char:3
+ Disconnect-VBRServer
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException
How can i fix this. Do i need to give any permission on the script?
Running the console As Administrator should do the trick.
I would also recommend jumping to the latest version (9.5.1).