PowerShell script exchange
Post Reply
chrishcn
Novice
Posts: 8
Liked: never
Joined: Oct 25, 2021 9:16 am
Full Name: Chris Huc
Contact:

Report Veeam Job - Need advice for improvement

Post by chrishcn »

Hello,

I made this script for reporting to my superiors and potentially trace the backup information of the subsidiaries afterwards.

I'm new to powershell and scripting so I think it's not super optimized. I wanted to do it by myself to learn (except html part).

1- Can you help me improve it through advice or method that I could have applied?
2- I cannot find how to get reverse incremental information. If the backup mode is reverse incremental, it always displays Incremental.
3- Also the search for tape jobs takes time (on average one minute per job according to measurement)

Code: Select all

<#
# Job Reporting
# Author: Me
# Script and data info: This script performs a reporting of current backup schedule
# Warning : It takes time
# 
#>


$result = @()

$vbrjobs = Get-VBRJob # Creating a list of Veeam Backup Job (not tape)

foreach($vbrjob in $vbrjobs){

    $name = $vbrjob.Name  # Job name    
    $description = $vbrjob.Description # Job description

    write-host "Gathering information for $name..." 
    
    # Getting data backed up informations
    $listdata = Get-VBRJobObject -Job $vbrjob  # Getting list of data backed up by the job
    $namedata= ($listdata | Where-Object type -eq Include).name  # Getting data name
    $sizedata = ($listdata | Where-Object type -eq Include).approxsizestring  # Getting data size

    # Getting schedules job
    write-host "Récupération des schedules..."
    $scheduledays = $vbrjob.Info.ScheduleOptions.OptionsDaily.DaysSrv
    $scheduleshours = "$($vbrjob.Info.ScheduleOptions.OptionsDaily.TimeLocal.Hour)h$($vbrjob.Info.ScheduleOptions.OptionsDaily.TimeLocal.minute)"
    $activefullday = $vbrjob.AutoScheduleOptions.ActiveFullBackupDays

    # Getting retention of job (not tape)    
    write-host "Récupération des rétentions (pas tape)..."
    $retention = $vbrjob.BackupStorageOptions.RetainCycles

    # Getting schedules tape job
    write-host "Récupération du schedule tape... Prend du temps!"
    $vbrjobtape = Get-VBRTapeJob | where {$_.object.name -eq $vbrjob.name}
    $mediapool = Get-VBRTapeMediaPool -Name $vbrjobtape.Target  # Name of the mediapool associated with the job
    
    if($mediapool.type -eq "GFS"){

        $weeklydayweek = $vbrjobtape.GFSScheduleOptions.WeeklyOptions.WeeklyDay
        $monthlydaynumber = $vbrjobtape.GFSScheduleOptions.MonthlyOptions.DayOfWeekNumber
        $monthlydayweek = $vbrjobtape.GFSScheduleOptions.MonthlyOptions.DayOfWeek
        $yearlydaynumber = $vbrjobtape.GFSScheduleOptions.YearlyOptions.DayOfWeekNumber
        $yearlydayweek = $vbrjobtape.GFSScheduleOptions.YearlyOptions.DayOfWeek
        $yearlymonth = $vbrjobtape.GFSScheduleOptions.YearlyOptions.MonthOfyear
    
        $tapeschedule = "$($weeklydayweek)/Weekly",
                        "$($monthlydaynumber)/$($monthlydayweek)/Monthly",
                        "$($yearlydaynumber)/$($yearlymonth)/$($yearlydayweek)/Yearly"
    } 

    else{
        $type = $vbrjobtape.ScheduleOptions.Type
        switch ( $type ) {
        "AfterJob" { $tapeschedule = 'AfterJob'    }
        "Daily" { $tapeschedule = "$($vbrjobtape.ScheduleOptions.DailyOptions.period)/$($vbrjobtape.ScheduleOptions.DailyOptions.DayOfWeek)"}
        "Monthly" {$tapeschedule = "$($vbrjobtape.ScheduleOptions.MonthlyOptions.period)/$($vbrjobtape.ScheduleOptions.MonthlyOptions.DayOfWeek)" }
        }

    }

    # Getting retention secondary targets
    write-host "Getting secondary target retention if exist"

    $vbrjoboptions = Get-VBRJobOptions -Job $vbrjob    # Shorcut name to get access to job properties

    if ($vbrjoboptions.sanintegrationoptions.SanSnapshotBackupTransferEnabled -eq "True"){
        $snapshottransfert = $vbrjoboptions.sanintegrationoptions.SanSnapshotBackupTransferRetention
    } else {$snapshottransfert = "N/A"}

    
    if ($vbrjoboptions.sanintegrationoptions.SanSnapshotSourceEnabled -eq "True"){
        $snapshotsource = $vbrjoboptions.sanintegrationoptions.SanSnapshotSourceRetention
    } else {$snapshotsource = "N/A"}

    # Getting Backup Mode
   write-host "Récupération du mode de backup"

    $fullnumber = $vbrjob.AutoScheduleOptions.ActiveFullBackupKind
    
    if ($vbrjoboptions.Options.RootNode.Algorithm -eq "Syntethic"){
          $backupmode = "Reversed Incremental"
       }
       if ($vbrjoboptions.Options.RootNode.Algorithm -eq "Increment") {
          if ($vbrjob.Options.Options.RootNode.TransformFullToSyntethic -eq "True" -And $vbrjoboptions.Options.RootNode.TransformIncrementsToSyntethic -eq "True") {
             $backupmode = "Incremental ( Synthetic full enabled, Transform previous full backup chains into rollbacks )"
          }
          if ($vbrjoboptions.Options.RootNode.TransformFullToSyntethic -eq "True" -And $vbrjoboptions.Options.RootNode.TransformIncrementsToSyntethic -eq "False") {
             $backupmode = "Incremental ( Synthetic full enabled )"
          }
          if ($vbrjoboptions.Options.RootNode.TransformFullToSyntethic -eq "False" -And $vbrjoboptions.Options.RootNode.TransformIncrementsToSyntethic -eq "False") {
             $backupmode = "Incremental ( Synthetic full disabled, Active full backups )"
          }
       }


# All info into $result variable

    $result += $vbrjob | select Name, 
    Description, 
    @{n='Data';e={$dataname}},
    @{n='DataSize';e={$sizedata}},
    @{n='ScheduleHours';e={$scheduleshours}},
    @{n='ScheduleDays';e={$scheduledays}},
    @{n='BackupMode';e={$backupmode}},
    @{n='ActiveFullDay';e={$activefullday}},
    @{n='RestorePointRepository';e={$retention}},
    @{n='SnapshotAFFA300';e={$snapshotsource}},
    @{n='SnapshotFAS2650';e={$snapshottransfert}},
    @{n='TapeJob';e={$vbrjobtape.name}},
    @{n='TapeSchedule';e={$tapeschedule}
}

}

# Send mail


$headerBackColor = '#4F81BD'  # backgroundcolor for column headers
$oddRowBackColor = '#DCE6F1'  # background color for odd rows

$style = @"
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>Report</title>
    <meta name="generator" content="PowerShell" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <style type="text/css">
    body {
        font-family: Verdana, Arial, Geneva, Helvetica, sans-serif;
        font-size: 12px;
        color: black;
    }
    table, td, th {
        border-color: black;
        border-style: solid;
        font-family: Verdana, Arial, Geneva, Helvetica, sans-serif;
        font-size: 11px;
    }
    table {
        border-width: 0 0 1px 1px;
        border-spacing: 0;
        border-collapse: collapse;
    }

    td, th {
        margin: 0;
        padding: 4px;
        border-width: 1px 1px 0 0;
        text-align: left;
    }
    th {
        color: white;
        background-color: $headerBackColor;
        font-weight: bold;
    }
    </style>
"@


$mymail = $result | ConvertTo-Html -Property Name,Description,Data,Datasize,Scheduleshours,ScheduleDays,BackupMode,ActiveFullDay,RestorePointRepository,SnapshotAFFA300,SnapshotFAS2650,TapeJob,TapeSchedule -Head $style | Out-String
$attachement = $mymail | Out-File .\backup-strategy.html
Send-MailMessage -BodyAsHtml $mymail -Attachments .\backup-strategy.html -from "me" -To "me" -SmtpServer smtp.directory.manitou.com -subject "Backup Strategy"

 

 

 



    
david.domask
Veeam Software
Posts: 1226
Liked: 322 times
Joined: Jun 28, 2016 12:12 pm
Contact:

Re: Report Veeam Job - Need advice for improvement

Post by david.domask » 1 person likes this post

Hi @chrishcn,

Looking at your script, I think the biggest culprit is that you're calling Get-VBRTapeJob for each iteration of your loop and there's not a need for this.

First, I would ask for the fix I mention in this post from Technical Support: powershell-f26/more-details-of-tape-bac ... ml#p460279

It will help a little, but the biggest change is so simply build your array of Tape Jobs before you start the loop and simply reference that array to get the relevant job object and do operations on it.

So instead of:

Code: Select all

$jobs = Get-VBRJob
foreach($j in $jobs){
$tJob = Get-VBRTapeJob -name $job.Name*
}
Do it like:

Code: Select all

$jobs = Get-VBRJob
$tJobs = Get-VBRTapeJob

foreach($j in $jobs){
$t = $tJobs | Where-Object {$_.Name -eq $j.name}
}
The fix + this change should greatly reduce the time of your script.

Edit: Also, I'm not sure how many jobs you have, but if it's a lot, switch to using a Generic List for $results instead of using a normal array and the += operation. += clones the array in memory every time you use it, and if you have a LOT of jobs, this can start to slow Powershell down a lot.

Add to the first line of your script:

using namespace System.Collections.Generic


Then when you make $results, do:

$results = [List[Object]]@()

To add to $results, do

$results.Add($someobject)

This means that you'll need to pack the details of the job into an object -- you can actually do it the way you do already with by saving all those properties into

$properties = @{
"stuff"
}

$JobResults = New-Object -Type PSCustom -Properties $properties

And then it should just be

$results.Add($JobResults)

It's a little more code to write, but if you have 100+ jobs, I suspect this will show another speed improvement. If it's < 50 jobs though, the way you have is fine I guess.
David Domask | Product Management: Principal Analyst
chrishcn
Novice
Posts: 8
Liked: never
Joined: Oct 25, 2021 9:16 am
Full Name: Chris Huc
Contact:

Re: Report Veeam Job - Need advice for improvement

Post by chrishcn »

Hello,

Sorry to answer that late, I was on vacation.

Thank you very much for your advice, you were right, building the array out of the loop grealty reduced time, it went from 10mn to 20 secondes!

I really appreciate your help!
david.domask
Veeam Software
Posts: 1226
Liked: 322 times
Joined: Jun 28, 2016 12:12 pm
Contact:

Re: Report Veeam Job - Need advice for improvement

Post by david.domask »

Hi @chrishcn,

No worries, I was also on holiday :D

I'm very glad that worked for you :) I suppose your team must be pretty happy with 30x increase ;)

Rest of script is fine as I can see it, as it's mostly cosmetic for your purposes for your presenting, but we can help :)
David Domask | Product Management: Principal Analyst
Post Reply

Who is online

Users browsing this forum: No registered users and 10 guests