PowerShell script exchange
Post Reply
z3r0
Novice
Posts: 4
Liked: 2 times
Joined: Apr 06, 2016 8:19 am
Full Name: Dom Herr

Get-VMs Backup Start- EndTime

Post by z3r0 » 1 person likes this post

Hello @ all,

i have to monitor my daily Veeam Backup Job results using the script below.
It is mainly the Script from http://blog.smasterson.com/2016/02/16/v ... rt-v9-0-1/ with some adjustments.

I need help to get the Backup Start- and EndTime from each VM in a specific BackupJob.


Code: Select all


Add-PSSnapin "VeeamPSSnapIn" -ErrorAction SilentlyContinue
 
#region User-Variables


#Kundename = (Jobname in Veeam und VM_Name)
$customer = "Test"

# Report mode - valid modes: any number of hours, Weekly or Monthly
# 24, 48, "Weekly", "Monthly"
$reportMode = 24
# Report Title
$rptTitle = "Kunde - $customer - Veeam Backup Report"
# Append Report Mode to Report Title E.g. My Veeam Report (Last 24 Hours)
$fullTitle = $true
# Report Width in Pixels
$rptWidth = 1750
# Only show last session for each Job
$onlyLast = $false

# Location of Veeam executable (Veeam.Backup.Shell.exe)
$veeamExePath = "C:\Program Files\Veeam\Backup and Replication\Backup\Veeam.Backup.Shell.exe"
# Location of common dll - Needed for repository function - Get-vPCRepoInfo (Veeam.Backup.Core.dll)
$veeamDllPath = "C:\Program Files\Veeam\Backup and Replication\Backup\Veeam.Backup.Core.dll"
# vCenter server(s) - As seen in VBR server
#$vcenters = "vcenter1","vcenter2"
$vcenters = "vcenter@mydomain.local"

# Show VMs with no successful backups within time frame ($reportMode)
$showUnprotectedVMs = $true
# Show VMs with successful backups within time frame ($reportMode)
$showProtectedVMs = $true
# To Exclude VMs from Missing and Successful Backups section add VM names to be excluded
# $excludevms = @("vm1","vm2","*_replica")
$excludeVMs = @("*$customer*")
# Exclude VMs from Missing and Successful Backups section in the following (vCenter) folder(s)
# $excludeFolder =  = @("folder1","folder2","*_testonly")
$excludeFolder = @("")
# Exclude VMs from Missing and Successful Backups section in the following (vCenter) datacenter(s)
# $excludeDC =  = @("dc1","dc2","dc*")
$excludeDC = @("")
# Show Running jobs
$showRunning = $true
# Show All Sessions w/Warnings or Failures within time frame ($reportMode)
$showWarnFail = $true
# Show All Successful Sessions within time frame ($reportMode)
$showSuccess = $true
# Show Repository Info
$showRepo = $true
# Show Proxy Info
$showProxy = $true
# Show Replica Target Info
$showReplica = $true
# Show Veeam Services Info (Windows Services)
$showServices = $true
# Show only Services that are NOT running
$hideRunningSvc = $false
# Show License expiry info
$showLicExp = $true

# Save output to a file - $true or $false
$saveFile = $True
# File output path and filename
$outFile = "C:\VeeamReports\Lokale_Report_Ablage\'$Customer'_Report_$(Get-Date -format MMddyyyy_hhmmss).htm"
# Launch file after creation - $true or $false
$launchFile = $false

# Email configuration
$sendEmail = $true
$emailHost = ""
$emailUser = ""
$emailPass = ""
$emailFrom = ""
$emailTo = ""
# Send report as attachment - $true or $false
$emailAttach = $true
# Email Subject 
$emailSubject = $rptTitle
# Append Report Mode to Email Subject E.g. My Veeam Report (Last 24 Hours)
$fullSubject = $true

# 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.4.1"
 
#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 all sessions
$allSesh = Get-VBRBackupSession | where { $_.JobName -like "*$customer*"}
# Get all the backup sessions for mode (timeframe)
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")}

#Get replica jobs
$repList = Get-VBRJob | ?{$_.IsReplica}

# Get session information
$totalxfer = 0
$totalRead = 0
$seshList | %{$totalxfer += $([Math]::Round([Decimal]$_.Progress.TransferedSize/1GB, 2))}
$seshList | %{$totalRead += $([Math]::Round([Decimal]$_.Progress.ReadSize/1GB, 2))}
If ($onlyLast) {
$tempSeshList = $seshList
$seshList = @()
foreach($job in (Get-VBRJob | ? {$_.JobType -eq "Backup"}))
{
$seshList += $TempSeshList | ?{$_.Jobname -eq $job.name} | Sort-Object CreationTime -Descending | Select-Object -First 1
}
}
$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")})

# Script abbrechen, wenn kein Backup lief
# Damit kein leerer Report gesendet wird
#$sessWFALL = @($warningSessions + $failsSessions + $succesSessions)
#if ($sessWFALL.count -eq 0) {Exit
#}

# Append Report Mode to Report Title
If ($fullTitle) {
If (($reportMode -ne "Weekly") -And ($reportMode -ne "Monthly")) {
        $rptTitle = "$rptTitle (Last $reportMode Hrs)"
} else {
        $rptTitle = "$rptTitle ($reportMode)"
}
}

# Append Report Mode to Email subject
If ($fullSubject) {
If (($reportMode -ne "Weekly") -And ($reportMode -ne "Monthly")) {
        $emailSubject = "$emailSubject (Last $reportMode Hrs)"
} else {
        $emailSubject = "$emailSubject ($reportMode)"
}
}
#endregion

#region Functions
 
function Get-vPCProxyInfo {
$vPCObjAry = @()
    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
            }
            return $vPCFuncObject
    }   
    Get-VBRViProxy | %{$vPCObjAry = $vPCObjAry + $(Build-vPCObj $_)}
$vPCObjAry
}
 
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, $repohost, $path, $free, $total)
                        $repoObj = New-Object -TypeName PSObject -Property @{
                                        Target = $name
RepoHost = $repohost.ToLower()
                                        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, RepoHost, 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.CWinFileCommander]::Create($Server.Info)
                                $storage = $FileCommander.GetDrives([ref]$null) | ?{$_.Name -eq $r.Path.Substring(0,3)}
                                $outputObj = Build-Object $r.Name $server.RealName $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 $server.RealName $r.Path $storage.FreeSpace $storage.TotalSize
                        }
                        elseif ($r.Type -eq "CifsShare") {
                                $Server = $r.GetHost()
$fso = New-Object -Com Scripting.FileSystemObject
                                $storage = $fso.GetDrive($r.Path)
# Catch shares with > 4TB space (not calculated correctly)
If (!($storage.TotalSize) -or (($storage.TotalSize -eq 4398046510080) -and ($storage.AvailableSpace -eq 4398046510080))){
    $outputObj = New-Object -TypeName PSObject -Property @{
                                        Target = $r.Name
RepoHost = $server.RealName.ToLower()
                                        Storepath = $r.Path
                                        StorageFree = "Unknown"
                                        StorageTotal = "Unknown"
                                        FreePercentage = "Unknown"
                                }
} Else {
                                $outputObj = Build-Object $r.Name $server.RealName $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 "5*"){
$pattern = "EXPIRATION DATE\=\d{1,2}\/\d{1,2}\/\d{1,4}"
}
elseif($script:VeeamVersion -like "6*"){
$pattern = "Expiration date\=\d{1,2}\/\d{1,2}\/\d{1,4}"
}
elseif($script:VeeamVersion -like "8*"){
$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 "8*"){
$expirationDate = [regex]::matches($VeeamLicInfo, $pattern)[0].Value.Split("=")[1]
$datearray = $expirationDate -split '/'
$expirationDate = Get-Date -Day $datearray[0] -Month $datearray[1] -Year $datearray[2]
$totalDaysLeft = ($expirationDate - (get-date)).Totaldays.toString().split(",")[0]
$totalDaysLeft = [int]$totalDaysLeft
$objoutput = New-Object -TypeName PSObject -Property @{
ExpDate = $expirationDate.ToShortDateString()
            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.ToLower()}}, @{Name="Service Name"; Expression = {$_.DisplayName}}, Status
    $outputAry = $outputAry + $output  
    }
$outputAry
}

function Get-VMsBackupStatus {
    param (
  [String]$vcenter)
  
# Convert exclusion list to simple regular expression
$excludevms_regex = ('(?i)^(' + (($script:excludeVMs | ForEach {[regex]::escape($_)}) -join "|") + ')$') -replace "\\\*", ".*"
$excludefolder_regex = ('(?i)^(' + (($script:excludeFolder | ForEach {[regex]::escape($_)}) -join "|") + ')$') -replace "\\\*", ".*"
$excludedc_regex = ('(?i)^(' + (($script:excludeDC | ForEach {[regex]::escape($_)}) -join "|") + ')$') -replace "\\\*", ".*"

$outputary = @() 
$vcenterobj = Get-VBRServer -Name $vcenter
$vmobjs = Find-VBRObject -Server $vcenterobj | 
Where-Object {$_.Type -eq "VirtualMachine" -and $_.VMFolderName -notmatch $excludefolder_regex} |
Where-Object {$_.Name -match $excludevms_regex} |
Where-Object {$_.GetParent("Datacenter") -notmatch $excludedc_regex}


$jobobjids = [Veeam.Backup.Core.CHierarchyObj]::GetObjectsOnHost($vcenterobj.id) | Where-Object {$_.Type -eq "Vm"}

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)  {
if(!$vms.ContainsKey($vm.JobObjId)) {
$vmdc = [string]$vm.GetParent("Datacenter")
Try {$vmclus = [string]$vm.GetParent("ClusterComputeResource")} Catch {$vmclus = ""}
$vms.Add($vm.JobObjId, @("!", $vmdc, $vmclus, $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 Successfuly 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.GetEnumerator() | Sort-Object Value
}

function Get-VMsMissingBackup {
param (
$vms)

$outputary = @()  
foreach ($vm in $vms) {
  if ($vm.Value[0] -eq "!") {
    $objoutput = New-Object -TypeName PSObject -Property @{
Datacenter = $vm.Value[1]
Cluster = $vm.Value[2]
Name = $vm.Value[3]
}
$outputAry += $objoutput
  }
}
$outputAry | Select Datacenter, Cluster, Name
}

function Get-VMsSuccessBackup {
param (
$vms)

$outputary = @()  
foreach ($vm in $vms) {
  if ($vm.Value[0] -ne "!") {
    $objoutput = New-Object -TypeName PSObject -Property @{
Datacenter = $vm.Value[1]
Cluster = $vm.Value[2]
Name = $vm.Value[3]
}
$outputAry += $objoutput
  }
}
$outputAry | Select Datacenter, Cluster, Name
}

#endregion
 
#region Report
# Get Veeam Version
$VeeamVersion = Get-VeeamVersion

If ($VeeamVersion -lt 8) {
Write-Host "Script requires VBR v8 or greater" -ForegroundColor Red
exit
}

# HTML Stuff
$headerObj = @"
<html>
        <head>
                <title>$rptTitle</title>
                <style>  
                        body {font-family: Tahoma; background-color:#fff;}
table {font-family: Tahoma;width: $($rptWidth)px;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>
<center>
                <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: 20%;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</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)</td>
                                <td style="width: 20%;height: 35px;border: none;background-color: #003366;color: White;font-size: 10px;vertical-align:bottom;text-align:right;padding: 2px 3px 2px 3px;">Veeam v$VeeamVersion</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;">
"@

$subHead01err = @"
                <table>
                        <tr>
                                <td style="height: 35px;background-color: #FF0000;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 = @"
</center>
</body>
</html>
"@

#Get VM Backup Status
$vmstatus = @()
foreach ($vcenter in $vcenters) {
$status = Get-VMsBackupStatus $vcenter 
$vmstatus += $status
}

# VMs Missing Backups
$missingVMs = @()
$missingVMs = Get-VMsMissingBackup $vmstatus

# VMs Successfuly Backed Up
$successVMs = @()
$successVMs = Get-VMsSuccessBackup $vmstatus 

# Get Summary Info
$vbrMasterHash = @{
"Coordinator" = "$((gc env:computername).ToLower())"
"Failed" = @($failedSessions).Count
"Sessions" = @($totalSessions).Count
"Read" = $totalRead
"Transferred" = $totalXfer
"Successful" = @($succesSessions).Count
"Warning" = @($warningSessions).Count
"Fails" = @($failsSessions).Count
"Running" = @($runningSessions).Count
"SuccessVM" = @($successVMs).Count 
"FailedVM" = @($missingVMs).Count
}
$vbrMasterObj = New-Object -TypeName PSObject -Property $vbrMasterHash

If ($onlyLast) {
$bodySummary =  $vbrMasterObj | Select Coordinator, @{Name="Unprotected VMs"; Expression = {$_.FailedVM}},
@{Name="Protected VMs"; Expression = {$_.SuccessVM}}, @{Name="Jobs Run"; Expression = {$_.Sessions}},
@{Name="Read (GB)"; Expression = {$_.Read}}, @{Name="Transferred (GB)"; Expression = {$_.Transferred}},
@{Name="Running"; Expression = {$_.Running}}, @{Name="Successful"; Expression = {$_.Successful}},
@{Name="Warnings"; Expression = {$_.Warning}},
@{Name="Failed"; Expression = {$_.Failed}} | ConvertTo-HTML -Fragment
} Else {
$bodySummary =  $vbrMasterObj | Select Coordinator, @{Name="Unprotected VMs"; Expression = {$_.FailedVM}},
@{Name="Protected VMs"; Expression = {$_.SuccessVM}}, @{Name="Total Sessions"; Expression = {$_.Sessions}},
@{Name="Read (GB)"; Expression = {$_.Read}}, @{Name="Transferred (GB)"; Expression = {$_.Transferred}},
@{Name="Running"; Expression = {$_.Running}}, @{Name="Successful"; Expression = {$_.Successful}},
@{Name="Warnings"; Expression = {$_.Warning}}, @{Name="Failures"; Expression = {$_.Fails}},
@{Name="Failed"; Expression = {$_.Failed}} | ConvertTo-HTML -Fragment
}



# Get VMs Missing Backups
$bodyMissing = $null
If ($showUnprotectedVMs) {
If ($missingVMs -ne $null) {
$missingVMs = $missingVMs | Sort Datacenter, Cluster, Name | ConvertTo-HTML -Fragment
$bodyMissing = $subHead01err + "VMs with No Successful Backups" + $subHead02 + $missingVMs
}
}

# Get VMs Successfuly Backed Up
$bodySuccess = $null
If ($showProtectedVMs) {
If ($successVMs -ne $null) {
$successVMs = $successVMs | Sort Datacenter, Cluster, Name | ConvertTo-HTML -Fragment
$bodySuccess = $subHead01 + "VMs with Successful Backups" + $subHead02 + $successVMs 
}
}

# Get Running Jobs
$bodyRunning = $null
if ($showRunning -eq $true) {
        if ($runningSessions.count -gt 0) {
                $bodyRunning = $runningSessions | Sort Creationtime | Select @{Name="Job Name"; Expression = {$_.Name}},
                @{Name="Start Time"; Expression = {$_.CreationTime}},
                @{Name="Duration (Mins)"; Expression = {[Math]::Round((New-TimeSpan $(Get-Date $_.Progress.StartTime) $(Get-Date)).TotalMinutes,2)}},
@{Name="% Complete"; Expression = {$_.Progress.Percents}},
                @{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
                $bodyRunning = $subHead01 + "Running Jobs" + $subHead02 + $bodyRunning
        }
} 

# Get Sessions with Failures or Warnings
$bodySessWF = $null
if ($showWarnFail -eq $true) {
        $sessWF = @($warningSessions + $failsSessions)
        if ($sessWF.count -gt 0) {
If ($onlyLast) {
$headerWF = "Jobs with Warnings or Failures"
} Else {
$headerWF = "Sessions with Warnings or Failures"
}
                $bodySessWF = $sessWF | Sort JobName | Select @{Name="Job Name"; Expression = {$_.Name}},
@{Name="Start Time"; Expression = {$_.CreationTime}},
                @{Name="Stop Time"; Expression = {$_.EndTime}},
@{Name="Duration (Mins)"; Expression = {[Math]::Round($_.WorkDetails.WorkDuration.TotalMinutes,2)}},
@{Name="Details"; Expression = {
If ($_.GetDetails() -eq ""){($_.GetDetails()).Replace("<br />"," - ") + ($_ | Get-VBRTaskSession | %{If ($_.GetDetails()){$_.Name + ": " + $_.GetDetails()}})}
Else {($_.GetDetails()).Replace("<br />"," - ")}}},
Result  | ConvertTo-HTML -Fragment
                $bodySessWF = $subHead01 + $headerWF + $subHead02 + $bodySessWF
        }
}

# Get Successful Sessions
$bodySessSucc = $null
if ($showSuccess -eq $true) {
       if ($succesSessions.count -gt 0) {
   If ($onlyLast) {
$headerSucc = "Successful Jobs"
} Else {
$headerSucc = "Successful Sessions"
}
                $bodySessSucc = $succesSessions | Sort JobName | Select @{Name="Job Name"; Expression = {$_.Name}},
                @{Name="Start Time"; Expression = {$_.CreationTime}},
                @{Name="Stop Time"; Expression = {$_.EndTime}},
@{Name="Duration (Mins)"; Expression = {[Math]::Round($_.WorkDetails.WorkDuration.TotalMinutes,2)}},
Result  | ConvertTo-HTML -Fragment
                $bodySessSucc = $subHead01 + $headerSucc + $subHead02 + $bodySessSucc
        }
}

# Combine HTML Output
$htmlOutput = $headerObj + $bodyTop + $bodySummary + $bodySessWF + $bodySessSucc + $bodySuccess + $bodyRunning + $bodyRepo + $bodyProxy + $bodyReplica + $bodyServices + $bodyLicense + $footerObj

# Add color to output depending on results
#Green
$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>Success<","<td style=""background-color: Green;color: White;"">Success<")
#Yellow
$htmlOutput = $htmlOutput.Replace("<td>Warning<","<td style=""background-color: Yellow;"">Warning<")
#Red
$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<")
#endregion
 
#region Output
if ($sendEmail) {
        $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 = "Backup Report für '$customer' im Anhang"
$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
}
}
        
If ($saveFile) {       
$htmlOutput | Out-File $outFile
If ($launchFile) {
Invoke-Item $outFile
}
}
#endregion


The Result (HTML Report) looks like this example:
Image

If i am using the Veeam Backup Enterprise Manager, i am able to get these VM details

Image

How may address these information?
Thanks in advance
PTide
Product Manager
Posts: 6431
Liked: 729 times
Joined: May 19, 2015 1:46 pm
Contact:

Re: Get-VMs Backup Start- EndTime

Post by PTide »

Hi and welcome to the community!

Have you already seen these this thread? Please let me know if it was helpful.

Thank you.
z3r0
Novice
Posts: 4
Liked: 2 times
Joined: Apr 06, 2016 8:19 am
Full Name: Dom Herr

Re: Get-VMs Backup Start- EndTime

Post by z3r0 » 1 person likes this post

Hi PTide,

thanks you so much. I didn't find this thread. :)

Now i have to include the results in my HTML output. The next challenge...

My thread can be marked as solved.

Regards
Post Reply

Who is online

Users browsing this forum: No registered users and 20 guests