Veeam Report ReDux!
A couple of months ago I posted about some Powershell I had written to report on the state of our Veeam backups.
I've been somewhat industrious here and am now on V3 of my script.
Requirements :
Things to do:
Here it is.
#
# Veeam Report
#
# Daily Veeam Report
#
# Version 3
#
# Allen Kong 09/01/205
#
# Psuedo Code
# 1. Get All vms from vSphere
# 1a. Connect to vSphere
# 2. Get all sessions in the last 24 hours from Veeam
# 3. Get all sessions in the last 5 days from Veeam
# 4. Process the data
# 5. Email the data
#
# 1. Get All vms from vSphere
Function GetAllVMs(){
#
# This function connects to vSphere and returns all the VMs registered in vSphere
# Change this to you vSphere server!
#
$viServer = "Server1"
# Add PowerShell VMware Snapin
Add-PSSnapin "Vmware.VIMAutomation.Core"
# Connect to vSphere
$server = Connect-VIServer $viServer -User "DOMAIN\Account" -Password "Password"
# Grab the VMs sorting them by VM Name
$serverList = Get-VM | Sort-Object Name
# Disconnect from vSphere
Disconnect-VIServer $server -confirm:$false
# Return data
$serverList
}
Function GetAllBackups(){
#
# This function loops through all the servers
# and then the sessions (veeam sessions) looking for a name match between server and session
# if found then the session is added to $output and the loop broken
# Effectively this checks all veeam sessions against the vSphere machines and returns matches.
#
# Probably don't need to do this as all sessions will (should) have a server they are based on
#
param($serverList, $sessions)
$output = @()
foreach($server in $serverList){
foreach($session in $sessions){
if($server.Name -eq $session.Name){
$output += $session
break
}
}
}
$output
}
Function GetAllReplicas(){
#
# This function loops through all the servers
# and then the sessions (veeam sessions) looking for a name match between server and session
# if found then the session is added to $output and the loop broken
# Effectively this checks all veeam sessions against the vSphere machines and returns matches.
#
# This is needed as replica sessions are named after the source machine where as the target VM is postfixed with _Replica
#
param($serverList, $sessions)
$output = @()
foreach($server in $serverList){
foreach($session in $sessions){
$name = ($session.Name) + "_Replica"
if($name -eq $server.Name){
$output += $session
break
}
}
}
$output
}
# 2. Get all sessions in the last 24 hours from Veeam
Function GetAllSession24hrs(){
#
# This function connects to the given server and request all the sessions based on the $type
#
# A new data type is created to store the information from the Veeam Session
# This is needed as some data is referenced in objects outside the Veeam Session : $task.Progress.StartTime
#
param($serverName, $type)
# Start new powershell session on the veeam server
$session = New-PSSession -ComputerName $serverName
# Load Veeam SnapIns
icm -Session $session -ScriptBlock {Add-PSSnapin -Name VeeamPSSnapIn}
switch($type){
# Grab all the Veeam session information for the last 24hrs
"Backup" {icm -Session $session -ScriptBlock {$vbrSessions = Get-VBRBackupSession | ? {$_.JobType -eq "Backup" -and $_.EndTime -ge (Get-Date).addhours(-24)} | Sort-Object JobName};break}
# Grab all the Veeam session information for the last 24hrs
"Replica" {icm -Session $session -ScriptBlock {$vbrSessions = Get-VBRBackupSession | ? {$_.JobType -eq "Replica" -and $_.EndTime -ge (Get-Date).addhours(-24)} | Sort-Object JobName};break}
}
# Somewhere to store the data
$veeamArray = @();
$veeamArray =
icm -Session $session -ScriptBlock {
param($type)
# Run through each session
foreach($vbrSession in $vbrSessions){
# Run into the VMs
foreach($task in $vbrSession.gettasksessions()){
# Make vm object
$vm = 1 | Select Name, Status, Date, JobName, SessionName, Retry, Type
$vm.Name = $task.Name
$vm.Status = $task.Status
$vm.Date = $task.Progress.StartTime
$vm.JobName = $task.JobName
$vm.SessionName = $vbrSession.Name
$vm.Retry = 0
$vm.Type = $type
if($vm.SessionName -match "Retry"){
$string = $vm.SessionName
$vm.Retry = $string.SubString($string.Length - 2, 1)
}
# Add vm to the array
$vm
}
}
} -ArgumentList $type
# Close the session
Remove-PSSession $session
# Return the data
$veeamArray
}
# 3. Get all sessions in the last 5 days (120 hours) from Veeam
Function GetAllSessions5Days(){
#
# NOT USED YET
#
param($serverName, $type)
# Start new powershell session on the veeam server
$session = New-PSSession -ComputerName $serverName
# Load Veeam SnapIns
icm -Session $session -ScriptBlock {Add-PSSnapin -Name VeeamPSSnapIn}
switch($type){
# Grab all the Veeam session information for the last 24hrs
"Backup" {icm -Session $session -ScriptBlock {$vbrSessions = Get-VBRBackupSession | ? {$_.JobType -eq "Backup" -and $_.EndTime -ge (Get-Date).addhours(-120)} | Sort-Object Name};break}
# Grab all the Veeam session information for the last 24hrs
"Replica" {icm -Session $session -ScriptBlock {$vbrSessions = Get-VBRBackupSession | ? {$_.JobType -eq "Replica" -and $_.EndTime -ge (Get-Date).addhours(-120)} | Sort-Object Name};break}
}
# Somewhere to store the data
$veeamArray = @();
$veeamArray =
icm -Session $session -ScriptBlock {
param($type)
# Run through each session
foreach($vbrSession in $vbrSessions){
# Run into the VMs
foreach($task in $vbrSession.gettasksessions()){
# Make vm object
$vm = 1 | Select Name, Status, Date, JobName, SessionName, Retry, Type
$vm.Name = $task.Name
$vm.Status = $task.Status
$vm.Date = $task.Progress.StartTime
$vm.JobName = $task.JobName
$vm.SessionName = $vbrSession.Name
$vm.Retry = 0
$vm.Type = $type
if($vm.SessionName -match "Retry"){
$string = $vm.SessionName
$vm.Retry = $string.SubString($string.Length - 2, 1)
}
# Add vm to the array
$vm
}
}
} -ArgumentList $type
# Close the session
Remove-PSSession $session
# Return the data
$veeamArray
}
# 4. Process the data
Function MatchServerToSession(){
#
# This function finds all servers which have a corresponding session
# Filter is inplace for replicas
#
param($serverlist, $veeamdata)
$output = @()
foreach($server in $serverlist){
foreach($session in $veeamdata){
if(($server.name -eq $session.name) -or (($server.name + "_Replica") -eq $session.name)){
$output += $server
break
}
}
}
$output
}
Function NotMatchServerToSession(){
#
# This function finds all servers which DO NOT have a corresponding session
# Filter is inplace for replicas
#
param($serverlist, $veeamdata)
$output = @()
$flag = 0
foreach($server in $serverlist){
foreach($session in $veeamdata){
if(($server.name -eq $session.name) -or (($session.name + "_replica") -eq $server.name)){
$flag = 999
break
}
}
if($flag -eq 0){
$output += $server
}
else{
$flag = 0
}
}
$output
}
Function GetFailures(){
#
# This function finds all veeam sessions which have failed
# This is used in sending failure emails to ServiceDesk to raise calls
#
param($sessions)
$output = @()
foreach($session in $sessions){
$state = $session.Status.Value
if($state -eq "Failed"){
$output += $session
}
}
$output
}
# 5. Send Email
Function sendEmail{
param($from,$to,$subject,$smtphost,$htmlFileName)
$body = Get-Content $htmlFileName
$smtp= New-Object System.Net.Mail.SmtpClient $smtphost
$msg = New-Object System.Net.Mail.MailMessage $from, $to, $subject, $body
$msg.isBodyhtml = $true
$smtp.send($msg)
}
Function sendTxtEmail{
param($from,$to,$subject,$smtphost,$body)
$smtp= New-Object System.Net.Mail.SmtpClient $smtphost
$msg = New-Object System.Net.Mail.MailMessage $from, $to, $subject, $body
$msg.isBodyhtml = $true
$smtp.send($msg)
}
Function sendFailures(){
param($data)
foreach($session in $data){
$sessionName = $session.Name
sendTxtEmail veeam@contoso.com ithelpdesk@contoso.com "Veeam Failure" <SMTP_IP> "Veeam Job Failed $sessionName Please assign accordingly"
}
}
# 5a. Write data
Function writeHeader(){
param($filename, $serverTotal, $sessionTotal, $successTotal, $failedTotal, $warningTotal, $omittedTotal)
$date = ( Get-Date ).ToString('yyyy/MM/dd')
Add-Content $fileName "<html>"
Add-Content $fileName "<head>"
Add-Content $fileName "<meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'>"
Add-Content $fileName '<title>Veeam Backup Report</title>'
Add-Content $fileName '<STYLE TYPE="text/css">'
Add-Content $fileName "<!--"
Add-Content $fileName "td {"
Add-Content $fileName "font-family: Tahoma;"
Add-Content $fileName "font-size: 11px;"
Add-Content $fileName "border-top: 1px solid #999999;"
Add-Content $fileName "border-right: 1px solid #999999;"
Add-Content $fileName "border-bottom: 1px solid #999999;"
Add-Content $fileName "border-left: 1px solid #999999;"
Add-Content $fileName "padding-top: 0px;"
Add-Content $fileName "padding-right: 0px;"
Add-Content $fileName "padding-bottom: 0px;"
Add-Content $fileName "padding-left: 0px;"
Add-Content $fileName "}"
Add-Content $fileName ".input-color {"
Add-Content $fileName "position: relative;"
Add-Content $fileName "}"
Add-Content $fileName ".input-color input {"
Add-Content $fileName "padding-left: 20px;"
Add-Content $fileName "}"
Add-Content $fileName ".input-color .color-box {"
Add-Content $fileName "width: 10px;"
Add-Content $fileName "height: 10px;"
Add-Content $fileName "display: inline-block;"
Add-Content $fileName "background-color: #ccc;"
Add-Content $fileName "position: absolute;"
Add-Content $fileName "left: 5px;"
Add-Content $fileName "top: 5px;"
Add-Content $fileName "}"
Add-Content $fileName "body {"
Add-Content $fileName "margin-left: 5px;"
Add-Content $fileName "margin-top: 5px;"
Add-Content $fileName "margin-right: 0px;"
Add-Content $fileName "margin-bottom: 10px;"
Add-Content $fileName ""
Add-Content $fileName "table {"
Add-Content $fileName "border: thin solid #000000;"
Add-Content $fileName "}"
Add-Content $fileName "-->"
Add-Content $fileName "</style>"
Add-Content $fileName "</head>"
Add-Content $fileName "<body>"
Add-Content $fileName "<table width='60%'>"
Add-Content $fileName "<tr bgcolor='#CCCCCC'>"
Add-Content $fileName "<td colspan='6' height='25' align='center'>"
Add-Content $fileName "<font face='tahoma' color='#003399' size='3'><strong>vSphere 24hr Backup Report V3 - $date</strong></font>"
Add-Content $fileName "</td>"
Add-Content $fileName "<tr align='center'><td colspan='6'> </td></tr>"
Add-Content $fileName "<tr align='center'>"
Add-Content $fileName "<td>Total Servers: $serverTotal</td>"
Add-Content $fileName "<td>Total Sessions: $sessionTotal</td>"
Add-Content $fileName "<td>Total Success: $successTotal</td>"
Add-Content $fileName "<td>Total Failed: $failedTotal</td>"
Add-Content $fileName "<td>Total Warning: $warningTotal</td>"
Add-Content $fileName "<td>Total Omitted: $omittedTotal</td>"
Add-Content $fileName "</tr>"
Add-Content $fileName "<tr align='center'><td colspan='6'> </td></tr>"
Add-Content $fileName "<tr align='center'>"
Add-Content $fileName "<td bgcolor='#8CDD81'>Veeam Backup Successful</td>"
Add-Content $fileName "<td bgcolor='#FBEC5D'>Veeam Backup Warning</td>"
Add-Content $fileName "<td bgcolor='#EE0000'>Veeam Backup Failed</td>"
Add-Content $fileName "<td bgcolor='#79CDCD'>Veeam Backup Not in Place Planned</td>"
Add-Content $fileName "<td bgcolor='#FF9955'>Veeam Backup Not in Place Unplanned</td>"
Add-Content $fileName "<td bgcolor='#DDDDDD'>No Information</td>"
Add-Content $fileName "</tr>"
Add-Content $fileName "</tr>"
Add-Content $fileName "</table>"
}
Function writeFooter(){
param($filename)
Add-Content $fileName "</body>"
Add-Content $fileName "</HTML>"
}
Function writeBackupDataTableHeader{
param($fileName)
Add-Content $fileName "<table width='60%'><tbody>"
Add-Content $fileName "<tr bgcolor=#CCCCCC>"
Add-Content $fileName "<td colspan='3' align='center'><font size='2'face='tahoma' color='#003399'><strong>Backup Sessions</strong></font></td>"
Add-Content $fileName "</tr>"
Add-Content $fileName "<tr bgcolor=#CCCCCC>"
Add-Content $fileName "<td width='30%' align='center'><font size='2'face='tahoma' color='#003399'><strong>Server Name</strong></font></td>"
Add-Content $fileName "<td width='30%' align='center'><font size='2'face='tahoma' color='#003399'><strong>Status</strong></font></td>"
Add-Content $fileName "<td width='40%' align='center'><font size='2'face='tahoma' color='#003399'><strong>Job Name</strong></font></td>"
Add-Content $fileName "</tr>"
}
Function writeBackupDataTable{
param($fileName, $vms)
foreach($vm in $vms){
$colour = "DDDDDD"
$ServerName = $vm.Name
$ServerStatus = $vm.Status.Value
$sessionName = $vm.SessionName
$Retry = $vm.Retry
# Make Failures Red etc...
switch($ServerStatus){
"Failed"{$colour = "ff0000";break}
"Success"{$colour = "8CDD81";break}
"Warning"{$colour = "FBEC5D";break}
}
Add-Content $fileName "<tr bgcolor=$colour>"
Add-Content $fileName "<td align='center'>$ServerName</td>"
Add-Content $fileName "<td align='center'>$ServerStatus</td>"
Add-Content $fileName "<td align='center'>$SessionName</td>"
Add-Content $fileName "</tr>"
}
}
Function writeBackupDataTableFooter{
param($filename)
Add-Content $fileName "</tbody></table>"
}
Function writeReplicaDataTableHeader{
param($fileName)
Add-Content $fileName "<table width='60%'><tbody>"
Add-Content $fileName "<tr bgcolor=#CCCCCC>"
Add-Content $fileName "<td colspan='3' align='center'><font size='2'face='tahoma' color='#003399'><strong>Replica Sessions</strong></font></td>"
Add-Content $fileName "</tr>"
Add-Content $fileName "<tr bgcolor=#CCCCCC>"
Add-Content $fileName "<td width='30%' align='center'><font size='2'face='tahoma' color='#003399'><strong>Server Name</strong></font></td>"
Add-Content $fileName "<td width='30%' align='center'><font size='2'face='tahoma' color='#003399'><strong>Status</strong></font></td>"
Add-Content $fileName "<td width='40%' align='center'><font size='2'face='tahoma' color='#003399'><strong>Job Name</strong></font></td>"
Add-Content $fileName "</tr>"
}
Function writeReplicaDataTable(){
param($filename, $vms)
foreach($vm in $vms){
$colour = "DDDDDD"
$ServerName = $vm.Name
$ServerStatus = $vm.Status.Value
$sessionName = $vm.SessionName
$Retry = $vm.Retry
# Make Failures Red etc...
switch($ServerStatus){
"Failed"{$colour = "ff0000";break}
"Success"{$colour = "8CDD81";break}
"Warning"{$colour = "FBEC5D";break}
}
Add-Content $fileName "<tr bgcolor=$colour>"
Add-Content $fileName "<td align='center'>$ServerName</td>"
Add-Content $fileName "<td align='center'>$ServerStatus</td>"
Add-Content $fileName "<td align='center'>$SessionName</td>"
#Add-Content $fileName "<td align='center'>$Retry</td>"
Add-Content $fileName "</tr>"
}
}
Function writeReplicaDataTableFooter{
param($filename)
Add-Content $fileName "</tbody></table>"
}
Function writeDataTableFooter{
param($filename)
Add-Content $fileName "</tbody></table>"
}
Function writeMissingDataTableHeader{
param($fileName)
Add-Content $fileName "<table width='60%'><tbody>"
Add-Content $fileName "<tr bgcolor=#CCCCCC>"
Add-Content $fileName "<td colspan='2' align='center'><font size='2'face='tahoma' color='#003399'><strong>Remaining Servers</strong></font></td>"
Add-Content $fileName "</tr>"
Add-Content $fileName "<tr bgcolor=#CCCCCC>"
Add-Content $fileName "<td width='50%' align='center'><font size='2'face='tahoma' color='#003399'><strong>Server Name</strong></font></td>"
Add-Content $fileName "<td width='50%' align='center'><font size='2'face='tahoma' color='#003399'><strong>Server Notes</strong></font></td>"
Add-Content $fileName "</tr>"
}
Function writeMissingDataTable(){
param($filename, $vms)
foreach($vm in $vms){
$ServerName = $vm.Name
$ServerNotes = $vm.Notes
$colour = "FF9955"
switch -wildcard ($ServerNotes){
""{$colour = "#DDDDDD";break}
"*Not Backed Up*"{$colour = "79CDCD";break}
}
Add-Content $fileName "<tr bgcolor=$colour>"
Add-Content $fileName "<td align='center'>$ServerName</td>"
Add-Content $fileName "<td align='center'>$ServerNotes</td>"
Add-Content $fileName "</tr>"
}
}
Function writeMissingDataTableFooter{
param($filename)
Add-Content $fileName "</tbody></table>"
}
Function writeHTML(){
param($filename, $backups, $replicas, $missing, $servers)
$totalSessions = $backups.Count + $replicas.Count
$totalServers = $servers.Count
$totalMissing = $missing.Count
$totalSuccess = 0
$totalWarning = 0
$totalFailed = 0
foreach($vm in $backups){
$status = $vm.Status.Value
switch($status){
"Failed"{$totalFailed++;break}
"Success"{$totalSuccess++;break}
"Warning"{$totalWarning++;break}
}
}
foreach($vm in $replicas){
$status = $vm.Status.Value
switch($status){
"Failed"{$totalFailed++;break}
"Success"{$totalSuccess++;break}
"Warning"{$totalWarning++;break}
}
}
writeHeader $filename $totalServers $totalSessions $totalSuccess $totalFailed $totalWarning $totalMissing
writeBackupDataTableHeader $filename
writeBackupDataTable $filename $backups
writeBackupDataTableFooter $filename
writeReplicaDataTableHeader $filename
writeReplicaDataTable $filename $replicas
writeReplicaDataTableFooter $filename
writeMissingDataTableHeader $filename
writeMissingDataTable $filename $missing
writeMissingDataTableFooter $filename
writeDataTableFooter $filename
writeFooter $filename
}
# Variables for storing data
$date = ( Get-Date ).ToString('yyyyMMdd')
$filename = "C:\Scripts\veeam_daily_report_v3_$date.html"
# Array declaration
$allvirtualmachines = @()
$sessions5days = @()
$sessions24hr = @()
$sessionsMatched = @()
$sessionsNotMatched = @()
$backupfailures = @()
$replicafailures = @()
$sessionsBackups = @()
$sessionsReplicas = @()
# Get vSphere Servers
$allvirtualmachines = GetAllVMs
########################################################
#
# Get Veeam Sessions - add your Veeam servers here!
#
########################################################
$veeamServers = @("server1","server2","server3")
########################################################
#
########################################################
foreach($veeam in $veeamServers){
# Run through each server and get the data
$sessionsBackups += (GetAllSession24hrs $veeam "Backup") | Sort Date -Descending
$sessionsReplicas += (GetAllSession24hrs $veeam "Replica") | Sort Date -Descending
}
$sessions24hr = $sessionsBackups + $sessionsReplicas
# Remove extra jobs
$sessionsBackup24hrProcessed = (GetAllBackups $allvirtualmachines $sessionsBackups) | sort Status -Descending
$sessionsReplica24hrProcessed = (GetAllBackups $allvirtualmachines $sessionsReplicas) | sort Status -Descending
# Find all servers with/without a Veeam Job
$serversMatched = MatchServerToSession $allvirtualmachines $sessions24hr
$serversNotMatched = NotMatchServerToSession $allvirtualmachines $sessions24hr
# Remove any old html files
if(Test-Path($filename)){
Remove-Item $filename
}
# Get all failures
$backupfailures = GetFailures $sessionsBackup24hrProcessed
$replicafailures = GetFailures $sessionsReplica24hrProcessed
writeHTML $filename $sessionsBackup24hrProcessed $sessionsReplica24hrProcessed $serversNotMatched $allvirtualmachines
# Email IT Helpdesk with Failures
sendFailures $backupfailures
sendFailures $replicafailures
# Email Report!
sendEmail veeam@contoso.com allen.kong@contoso.com "Veeam Report" <SMTPIP> $filename
I've been somewhat industrious here and am now on V3 of my script.
Requirements :
- You need to run this from a vSphere install
- You need Powershell 3 or 4 on vSphere and any Veeam servers
- You need Powershell remoting enabled on all involved servers
- As this is an unsigned script you need the execute policy set to unrestricted
- Edit the script for your environment...SMTP-IP, veeamServers and viServer.
Things to do:
- Get this running the vSphere stuff remotely...no idea why this wont work!
Here it is.
#
# Veeam Report
#
# Daily Veeam Report
#
# Version 3
#
# Allen Kong 09/01/205
#
# Psuedo Code
# 1. Get All vms from vSphere
# 1a. Connect to vSphere
# 2. Get all sessions in the last 24 hours from Veeam
# 3. Get all sessions in the last 5 days from Veeam
# 4. Process the data
# 5. Email the data
#
# 1. Get All vms from vSphere
Function GetAllVMs(){
#
# This function connects to vSphere and returns all the VMs registered in vSphere
# Change this to you vSphere server!
#
$viServer = "Server1"
# Add PowerShell VMware Snapin
Add-PSSnapin "Vmware.VIMAutomation.Core"
# Connect to vSphere
$server = Connect-VIServer $viServer -User "DOMAIN\Account" -Password "Password"
# Grab the VMs sorting them by VM Name
$serverList = Get-VM | Sort-Object Name
# Disconnect from vSphere
Disconnect-VIServer $server -confirm:$false
# Return data
$serverList
}
Function GetAllBackups(){
#
# This function loops through all the servers
# and then the sessions (veeam sessions) looking for a name match between server and session
# if found then the session is added to $output and the loop broken
# Effectively this checks all veeam sessions against the vSphere machines and returns matches.
#
# Probably don't need to do this as all sessions will (should) have a server they are based on
#
param($serverList, $sessions)
$output = @()
foreach($server in $serverList){
foreach($session in $sessions){
if($server.Name -eq $session.Name){
$output += $session
break
}
}
}
$output
}
Function GetAllReplicas(){
#
# This function loops through all the servers
# and then the sessions (veeam sessions) looking for a name match between server and session
# if found then the session is added to $output and the loop broken
# Effectively this checks all veeam sessions against the vSphere machines and returns matches.
#
# This is needed as replica sessions are named after the source machine where as the target VM is postfixed with _Replica
#
param($serverList, $sessions)
$output = @()
foreach($server in $serverList){
foreach($session in $sessions){
$name = ($session.Name) + "_Replica"
if($name -eq $server.Name){
$output += $session
break
}
}
}
$output
}
# 2. Get all sessions in the last 24 hours from Veeam
Function GetAllSession24hrs(){
#
# This function connects to the given server and request all the sessions based on the $type
#
# A new data type is created to store the information from the Veeam Session
# This is needed as some data is referenced in objects outside the Veeam Session : $task.Progress.StartTime
#
param($serverName, $type)
# Start new powershell session on the veeam server
$session = New-PSSession -ComputerName $serverName
# Load Veeam SnapIns
icm -Session $session -ScriptBlock {Add-PSSnapin -Name VeeamPSSnapIn}
switch($type){
# Grab all the Veeam session information for the last 24hrs
"Backup" {icm -Session $session -ScriptBlock {$vbrSessions = Get-VBRBackupSession | ? {$_.JobType -eq "Backup" -and $_.EndTime -ge (Get-Date).addhours(-24)} | Sort-Object JobName};break}
# Grab all the Veeam session information for the last 24hrs
"Replica" {icm -Session $session -ScriptBlock {$vbrSessions = Get-VBRBackupSession | ? {$_.JobType -eq "Replica" -and $_.EndTime -ge (Get-Date).addhours(-24)} | Sort-Object JobName};break}
}
# Somewhere to store the data
$veeamArray = @();
$veeamArray =
icm -Session $session -ScriptBlock {
param($type)
# Run through each session
foreach($vbrSession in $vbrSessions){
# Run into the VMs
foreach($task in $vbrSession.gettasksessions()){
# Make vm object
$vm = 1 | Select Name, Status, Date, JobName, SessionName, Retry, Type
$vm.Name = $task.Name
$vm.Status = $task.Status
$vm.Date = $task.Progress.StartTime
$vm.JobName = $task.JobName
$vm.SessionName = $vbrSession.Name
$vm.Retry = 0
$vm.Type = $type
if($vm.SessionName -match "Retry"){
$string = $vm.SessionName
$vm.Retry = $string.SubString($string.Length - 2, 1)
}
# Add vm to the array
$vm
}
}
} -ArgumentList $type
# Close the session
Remove-PSSession $session
# Return the data
$veeamArray
}
# 3. Get all sessions in the last 5 days (120 hours) from Veeam
Function GetAllSessions5Days(){
#
# NOT USED YET
#
param($serverName, $type)
# Start new powershell session on the veeam server
$session = New-PSSession -ComputerName $serverName
# Load Veeam SnapIns
icm -Session $session -ScriptBlock {Add-PSSnapin -Name VeeamPSSnapIn}
switch($type){
# Grab all the Veeam session information for the last 24hrs
"Backup" {icm -Session $session -ScriptBlock {$vbrSessions = Get-VBRBackupSession | ? {$_.JobType -eq "Backup" -and $_.EndTime -ge (Get-Date).addhours(-120)} | Sort-Object Name};break}
# Grab all the Veeam session information for the last 24hrs
"Replica" {icm -Session $session -ScriptBlock {$vbrSessions = Get-VBRBackupSession | ? {$_.JobType -eq "Replica" -and $_.EndTime -ge (Get-Date).addhours(-120)} | Sort-Object Name};break}
}
# Somewhere to store the data
$veeamArray = @();
$veeamArray =
icm -Session $session -ScriptBlock {
param($type)
# Run through each session
foreach($vbrSession in $vbrSessions){
# Run into the VMs
foreach($task in $vbrSession.gettasksessions()){
# Make vm object
$vm = 1 | Select Name, Status, Date, JobName, SessionName, Retry, Type
$vm.Name = $task.Name
$vm.Status = $task.Status
$vm.Date = $task.Progress.StartTime
$vm.JobName = $task.JobName
$vm.SessionName = $vbrSession.Name
$vm.Retry = 0
$vm.Type = $type
if($vm.SessionName -match "Retry"){
$string = $vm.SessionName
$vm.Retry = $string.SubString($string.Length - 2, 1)
}
# Add vm to the array
$vm
}
}
} -ArgumentList $type
# Close the session
Remove-PSSession $session
# Return the data
$veeamArray
}
# 4. Process the data
Function MatchServerToSession(){
#
# This function finds all servers which have a corresponding session
# Filter is inplace for replicas
#
param($serverlist, $veeamdata)
$output = @()
foreach($server in $serverlist){
foreach($session in $veeamdata){
if(($server.name -eq $session.name) -or (($server.name + "_Replica") -eq $session.name)){
$output += $server
break
}
}
}
$output
}
Function NotMatchServerToSession(){
#
# This function finds all servers which DO NOT have a corresponding session
# Filter is inplace for replicas
#
param($serverlist, $veeamdata)
$output = @()
$flag = 0
foreach($server in $serverlist){
foreach($session in $veeamdata){
if(($server.name -eq $session.name) -or (($session.name + "_replica") -eq $server.name)){
$flag = 999
break
}
}
if($flag -eq 0){
$output += $server
}
else{
$flag = 0
}
}
$output
}
Function GetFailures(){
#
# This function finds all veeam sessions which have failed
# This is used in sending failure emails to ServiceDesk to raise calls
#
param($sessions)
$output = @()
foreach($session in $sessions){
$state = $session.Status.Value
if($state -eq "Failed"){
$output += $session
}
}
$output
}
# 5. Send Email
Function sendEmail{
param($from,$to,$subject,$smtphost,$htmlFileName)
$body = Get-Content $htmlFileName
$smtp= New-Object System.Net.Mail.SmtpClient $smtphost
$msg = New-Object System.Net.Mail.MailMessage $from, $to, $subject, $body
$msg.isBodyhtml = $true
$smtp.send($msg)
}
Function sendTxtEmail{
param($from,$to,$subject,$smtphost,$body)
$smtp= New-Object System.Net.Mail.SmtpClient $smtphost
$msg = New-Object System.Net.Mail.MailMessage $from, $to, $subject, $body
$msg.isBodyhtml = $true
$smtp.send($msg)
}
Function sendFailures(){
param($data)
foreach($session in $data){
$sessionName = $session.Name
sendTxtEmail veeam@contoso.com ithelpdesk@contoso.com "Veeam Failure" <SMTP_IP> "Veeam Job Failed $sessionName Please assign accordingly"
}
}
# 5a. Write data
Function writeHeader(){
param($filename, $serverTotal, $sessionTotal, $successTotal, $failedTotal, $warningTotal, $omittedTotal)
$date = ( Get-Date ).ToString('yyyy/MM/dd')
Add-Content $fileName "<html>"
Add-Content $fileName "<head>"
Add-Content $fileName "<meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'>"
Add-Content $fileName '<title>Veeam Backup Report</title>'
Add-Content $fileName '<STYLE TYPE="text/css">'
Add-Content $fileName "<!--"
Add-Content $fileName "td {"
Add-Content $fileName "font-family: Tahoma;"
Add-Content $fileName "font-size: 11px;"
Add-Content $fileName "border-top: 1px solid #999999;"
Add-Content $fileName "border-right: 1px solid #999999;"
Add-Content $fileName "border-bottom: 1px solid #999999;"
Add-Content $fileName "border-left: 1px solid #999999;"
Add-Content $fileName "padding-top: 0px;"
Add-Content $fileName "padding-right: 0px;"
Add-Content $fileName "padding-bottom: 0px;"
Add-Content $fileName "padding-left: 0px;"
Add-Content $fileName "}"
Add-Content $fileName ".input-color {"
Add-Content $fileName "position: relative;"
Add-Content $fileName "}"
Add-Content $fileName ".input-color input {"
Add-Content $fileName "padding-left: 20px;"
Add-Content $fileName "}"
Add-Content $fileName ".input-color .color-box {"
Add-Content $fileName "width: 10px;"
Add-Content $fileName "height: 10px;"
Add-Content $fileName "display: inline-block;"
Add-Content $fileName "background-color: #ccc;"
Add-Content $fileName "position: absolute;"
Add-Content $fileName "left: 5px;"
Add-Content $fileName "top: 5px;"
Add-Content $fileName "}"
Add-Content $fileName "body {"
Add-Content $fileName "margin-left: 5px;"
Add-Content $fileName "margin-top: 5px;"
Add-Content $fileName "margin-right: 0px;"
Add-Content $fileName "margin-bottom: 10px;"
Add-Content $fileName ""
Add-Content $fileName "table {"
Add-Content $fileName "border: thin solid #000000;"
Add-Content $fileName "}"
Add-Content $fileName "-->"
Add-Content $fileName "</style>"
Add-Content $fileName "</head>"
Add-Content $fileName "<body>"
Add-Content $fileName "<table width='60%'>"
Add-Content $fileName "<tr bgcolor='#CCCCCC'>"
Add-Content $fileName "<td colspan='6' height='25' align='center'>"
Add-Content $fileName "<font face='tahoma' color='#003399' size='3'><strong>vSphere 24hr Backup Report V3 - $date</strong></font>"
Add-Content $fileName "</td>"
Add-Content $fileName "<tr align='center'><td colspan='6'> </td></tr>"
Add-Content $fileName "<tr align='center'>"
Add-Content $fileName "<td>Total Servers: $serverTotal</td>"
Add-Content $fileName "<td>Total Sessions: $sessionTotal</td>"
Add-Content $fileName "<td>Total Success: $successTotal</td>"
Add-Content $fileName "<td>Total Failed: $failedTotal</td>"
Add-Content $fileName "<td>Total Warning: $warningTotal</td>"
Add-Content $fileName "<td>Total Omitted: $omittedTotal</td>"
Add-Content $fileName "</tr>"
Add-Content $fileName "<tr align='center'><td colspan='6'> </td></tr>"
Add-Content $fileName "<tr align='center'>"
Add-Content $fileName "<td bgcolor='#8CDD81'>Veeam Backup Successful</td>"
Add-Content $fileName "<td bgcolor='#FBEC5D'>Veeam Backup Warning</td>"
Add-Content $fileName "<td bgcolor='#EE0000'>Veeam Backup Failed</td>"
Add-Content $fileName "<td bgcolor='#79CDCD'>Veeam Backup Not in Place Planned</td>"
Add-Content $fileName "<td bgcolor='#FF9955'>Veeam Backup Not in Place Unplanned</td>"
Add-Content $fileName "<td bgcolor='#DDDDDD'>No Information</td>"
Add-Content $fileName "</tr>"
Add-Content $fileName "</tr>"
Add-Content $fileName "</table>"
}
Function writeFooter(){
param($filename)
Add-Content $fileName "</body>"
Add-Content $fileName "</HTML>"
}
Function writeBackupDataTableHeader{
param($fileName)
Add-Content $fileName "<table width='60%'><tbody>"
Add-Content $fileName "<tr bgcolor=#CCCCCC>"
Add-Content $fileName "<td colspan='3' align='center'><font size='2'face='tahoma' color='#003399'><strong>Backup Sessions</strong></font></td>"
Add-Content $fileName "</tr>"
Add-Content $fileName "<tr bgcolor=#CCCCCC>"
Add-Content $fileName "<td width='30%' align='center'><font size='2'face='tahoma' color='#003399'><strong>Server Name</strong></font></td>"
Add-Content $fileName "<td width='30%' align='center'><font size='2'face='tahoma' color='#003399'><strong>Status</strong></font></td>"
Add-Content $fileName "<td width='40%' align='center'><font size='2'face='tahoma' color='#003399'><strong>Job Name</strong></font></td>"
Add-Content $fileName "</tr>"
}
Function writeBackupDataTable{
param($fileName, $vms)
foreach($vm in $vms){
$colour = "DDDDDD"
$ServerName = $vm.Name
$ServerStatus = $vm.Status.Value
$sessionName = $vm.SessionName
$Retry = $vm.Retry
# Make Failures Red etc...
switch($ServerStatus){
"Failed"{$colour = "ff0000";break}
"Success"{$colour = "8CDD81";break}
"Warning"{$colour = "FBEC5D";break}
}
Add-Content $fileName "<tr bgcolor=$colour>"
Add-Content $fileName "<td align='center'>$ServerName</td>"
Add-Content $fileName "<td align='center'>$ServerStatus</td>"
Add-Content $fileName "<td align='center'>$SessionName</td>"
Add-Content $fileName "</tr>"
}
}
Function writeBackupDataTableFooter{
param($filename)
Add-Content $fileName "</tbody></table>"
}
Function writeReplicaDataTableHeader{
param($fileName)
Add-Content $fileName "<table width='60%'><tbody>"
Add-Content $fileName "<tr bgcolor=#CCCCCC>"
Add-Content $fileName "<td colspan='3' align='center'><font size='2'face='tahoma' color='#003399'><strong>Replica Sessions</strong></font></td>"
Add-Content $fileName "</tr>"
Add-Content $fileName "<tr bgcolor=#CCCCCC>"
Add-Content $fileName "<td width='30%' align='center'><font size='2'face='tahoma' color='#003399'><strong>Server Name</strong></font></td>"
Add-Content $fileName "<td width='30%' align='center'><font size='2'face='tahoma' color='#003399'><strong>Status</strong></font></td>"
Add-Content $fileName "<td width='40%' align='center'><font size='2'face='tahoma' color='#003399'><strong>Job Name</strong></font></td>"
Add-Content $fileName "</tr>"
}
Function writeReplicaDataTable(){
param($filename, $vms)
foreach($vm in $vms){
$colour = "DDDDDD"
$ServerName = $vm.Name
$ServerStatus = $vm.Status.Value
$sessionName = $vm.SessionName
$Retry = $vm.Retry
# Make Failures Red etc...
switch($ServerStatus){
"Failed"{$colour = "ff0000";break}
"Success"{$colour = "8CDD81";break}
"Warning"{$colour = "FBEC5D";break}
}
Add-Content $fileName "<tr bgcolor=$colour>"
Add-Content $fileName "<td align='center'>$ServerName</td>"
Add-Content $fileName "<td align='center'>$ServerStatus</td>"
Add-Content $fileName "<td align='center'>$SessionName</td>"
#Add-Content $fileName "<td align='center'>$Retry</td>"
Add-Content $fileName "</tr>"
}
}
Function writeReplicaDataTableFooter{
param($filename)
Add-Content $fileName "</tbody></table>"
}
Function writeDataTableFooter{
param($filename)
Add-Content $fileName "</tbody></table>"
}
Function writeMissingDataTableHeader{
param($fileName)
Add-Content $fileName "<table width='60%'><tbody>"
Add-Content $fileName "<tr bgcolor=#CCCCCC>"
Add-Content $fileName "<td colspan='2' align='center'><font size='2'face='tahoma' color='#003399'><strong>Remaining Servers</strong></font></td>"
Add-Content $fileName "</tr>"
Add-Content $fileName "<tr bgcolor=#CCCCCC>"
Add-Content $fileName "<td width='50%' align='center'><font size='2'face='tahoma' color='#003399'><strong>Server Name</strong></font></td>"
Add-Content $fileName "<td width='50%' align='center'><font size='2'face='tahoma' color='#003399'><strong>Server Notes</strong></font></td>"
Add-Content $fileName "</tr>"
}
Function writeMissingDataTable(){
param($filename, $vms)
foreach($vm in $vms){
$ServerName = $vm.Name
$ServerNotes = $vm.Notes
$colour = "FF9955"
switch -wildcard ($ServerNotes){
""{$colour = "#DDDDDD";break}
"*Not Backed Up*"{$colour = "79CDCD";break}
}
Add-Content $fileName "<tr bgcolor=$colour>"
Add-Content $fileName "<td align='center'>$ServerName</td>"
Add-Content $fileName "<td align='center'>$ServerNotes</td>"
Add-Content $fileName "</tr>"
}
}
Function writeMissingDataTableFooter{
param($filename)
Add-Content $fileName "</tbody></table>"
}
Function writeHTML(){
param($filename, $backups, $replicas, $missing, $servers)
$totalSessions = $backups.Count + $replicas.Count
$totalServers = $servers.Count
$totalMissing = $missing.Count
$totalSuccess = 0
$totalWarning = 0
$totalFailed = 0
foreach($vm in $backups){
$status = $vm.Status.Value
switch($status){
"Failed"{$totalFailed++;break}
"Success"{$totalSuccess++;break}
"Warning"{$totalWarning++;break}
}
}
foreach($vm in $replicas){
$status = $vm.Status.Value
switch($status){
"Failed"{$totalFailed++;break}
"Success"{$totalSuccess++;break}
"Warning"{$totalWarning++;break}
}
}
writeHeader $filename $totalServers $totalSessions $totalSuccess $totalFailed $totalWarning $totalMissing
writeBackupDataTableHeader $filename
writeBackupDataTable $filename $backups
writeBackupDataTableFooter $filename
writeReplicaDataTableHeader $filename
writeReplicaDataTable $filename $replicas
writeReplicaDataTableFooter $filename
writeMissingDataTableHeader $filename
writeMissingDataTable $filename $missing
writeMissingDataTableFooter $filename
writeDataTableFooter $filename
writeFooter $filename
}
# Variables for storing data
$date = ( Get-Date ).ToString('yyyyMMdd')
$filename = "C:\Scripts\veeam_daily_report_v3_$date.html"
# Array declaration
$allvirtualmachines = @()
$sessions5days = @()
$sessions24hr = @()
$sessionsMatched = @()
$sessionsNotMatched = @()
$backupfailures = @()
$replicafailures = @()
$sessionsBackups = @()
$sessionsReplicas = @()
# Get vSphere Servers
$allvirtualmachines = GetAllVMs
########################################################
#
# Get Veeam Sessions - add your Veeam servers here!
#
########################################################
$veeamServers = @("server1","server2","server3")
########################################################
#
########################################################
foreach($veeam in $veeamServers){
# Run through each server and get the data
$sessionsBackups += (GetAllSession24hrs $veeam "Backup") | Sort Date -Descending
$sessionsReplicas += (GetAllSession24hrs $veeam "Replica") | Sort Date -Descending
}
$sessions24hr = $sessionsBackups + $sessionsReplicas
# Remove extra jobs
$sessionsBackup24hrProcessed = (GetAllBackups $allvirtualmachines $sessionsBackups) | sort Status -Descending
$sessionsReplica24hrProcessed = (GetAllBackups $allvirtualmachines $sessionsReplicas) | sort Status -Descending
# Find all servers with/without a Veeam Job
$serversMatched = MatchServerToSession $allvirtualmachines $sessions24hr
$serversNotMatched = NotMatchServerToSession $allvirtualmachines $sessions24hr
# Remove any old html files
if(Test-Path($filename)){
Remove-Item $filename
}
# Get all failures
$backupfailures = GetFailures $sessionsBackup24hrProcessed
$replicafailures = GetFailures $sessionsReplica24hrProcessed
writeHTML $filename $sessionsBackup24hrProcessed $sessionsReplica24hrProcessed $serversNotMatched $allvirtualmachines
# Email IT Helpdesk with Failures
sendFailures $backupfailures
sendFailures $replicafailures
# Email Report!
sendEmail veeam@contoso.com allen.kong@contoso.com "Veeam Report" <SMTPIP> $filename
Comments
Post a Comment