PowerShell/Veeam

Here you will find the latest version of the PowerShell/Veeam scripts found on this blog

v9

Veeam v9 – My Veeam Report v9.0.3

v8

Veeam v8 – My Veeam Report turns 2.0!

Veeam v8 – Backing up a single VM with PowerShell

Veeam v8 – Changing Default Options After Upgrade

v7

My Veeam Report v1.2

Veeam – Updating job settings with PowerShell

Documenting Veeam Backup Job Settings

Veeam v7 – Backing up a single VM within a job

Advertisements

7 thoughts on “PowerShell/Veeam

  1. Ernie Bergan

    Your efforts in version 9.01 have been an incredible help to me in pulling specific information about backup and restore jobs. My first foray into a PowerShell script to derive a .CSV file focused on VMware backups and restores. I now need to expand the script to include Endpoint Backup information. Do you happen to know if there are logs begin written during Endpoint Backup operations that are exposed to the PowerShell environment, similar to the logs that are accessible in restore operations? I’m trying to get the backup size of each Endpoint Backup, and ideally whether the backup was full or incremental. I don’t see that information exposed as elements in Get-VBREPJob or VBREPSession.

    For VMware restore operations, I ended up writing a small function to look through the restore job log to pull information. IF similar information is logged for Endpoint jobs, I should be able to parse it.

    Admittedly, since Endpoint Backup is still free from Veeam, I understand why they have far fewer PowerPoint hooks in place for EP.

    Thank for sharing your great work.

    Reply
    1. smasterson Post author

      My guess is that these logs exist on the client and not the server. I’ve not seen anything beyond what you have mentioned. It will be interesting to see how they build upon the relationship between VB&R and EP.

      Reply
  2. Ernie Bergan

    Discovered that – for each EPSession, the repository is also creating information on a Restore Point. I was hoping to find an ID that would insure the Restore Point record I’m retrieving matches the Endpoint Protection session, but so far I have not seen how to make that connection. So I look for a restore point that is created during the EP Session.

    With apologies for my learning code, no doubt highly inefficient – here’s my current script. Anything good I learned from you. Lots of commented lines as I try different fields and approaches.

    param(
    [string]$vbrServer=”127.0.0.1″,
    [int]$vbrPort=9392,
    [string]$vbrUser,
    [string]$vbrPassword,
    [int]$LookBackHrs=48,
    [string]$outFile=””,
    [switch]$ConnectTest=$false
    )

    #$LookBackHrs = 2200 # Controls how many hours back to retrieve backup and restore jobs
    #$outFile = “E:\tmp\Veeam_APTARE_GenericBU_$(Get-Date -format MMddyyyy_hhmmss).csv” # Output file name
    #$outFile = “E:\tmp\Veeam_APTARE_GenericBU_v5.csv” # Output file name
    $Vendor = “‘Veeam'” #VendorName placed in CSV
    #$vbrServer = “10.2.3.159” #Veeam Server to be connected

    # Set variables to null

    $nullstrg=”‘null'”
    $outarray=@()
    $backuparray=@()
    $backupEParray=@()
    $restorearray=@()

    add-pssnapin “VeeamPSSnapIn” -WarningAction SilentlyContinue -ErrorAction SilentlyContinue
    Disconnect-VBRServer
    #write-host (‘ConnectTest = ‘ + $ConnectTest)

    if ($ConnectTest) {
    if (Test-NetConnection -port $vbrPort -Computername $vbrServer -InformationLevel Quiet )
    {write-host ‘vbrServer Pings’}
    #Exit
    else
    {write-host (‘ERROR: Unable to connect to ‘+$vbrServer+’. Please verify connectivity to ‘+$vbrServer+’ from collector server using port ‘+ $vbrPort)
    Throw (‘Test NetConnection to ‘+$vbrServer+’ on port 9392 fails.’)
    Exit
    }
    }

    if ($ConnectTest) {
    Try {
    Connect-VBRServer -User $vbrUser -Password $vbrPassword -server $vbrServer -Port $vbrPort -ErrorAction Stop -WarningAction Stop -Timeout 1
    }
    Catch {
    Write-Host (‘ERROR: Authentication failed. Verify credentials.’)
    Throw ‘Error connecting to Veeam Server. Check credentials’
    Exit
    }
    Write-Host ‘SUCCESS: Successfully connected to Veeam Server’
    Exit
    }

    Try {
    Connect-VBRServer -User $vbrUser -Password $vbrPassword -server $vbrServer -Port $vbrPort -ErrorAction Stop -WarningAction Stop -Timeout 5
    } Catch {
    Throw ‘Error connecting to Veeam Server’
    Exit
    }

    function Convert-HEXtoDECRes
    {

    param(
    [Parameter(ValueFromPipeline=$true, Position=0)]
    [string]$HEXr)
    $subHEXr=””
    $hexrint=””
    $subHEXr = $HEXr.Substring(0, $HEXr.IndexOf(“-“) )
    ForEach ($value in $subHEXr)
    {
    $hexrint = [Convert]::ToInt64($value,16) + $hexrint
    }
    RETURN $hexrint
    }

    Function Get-RestoreSize {

    [CmdletBinding()]
    param(
    [Parameter(ValueFromPipeline=$true, Position=0)]
    [string]$Inputstring
    )
    [hashtable]$RestoreInfo = @{}
    If($inputstring) {
    If ($inputstring.Contains(“=”)) {
    $NbrOfFiles = $inputstring.Substring($inputstring.IndexOf(“=”)+1, $inputstring.IndexOf(“files”)-$inputstring.IndexOf(“=”) -2 )
    } else
    { $NbrOfFiles = 0}
    If ($inputstring.Contains(“(“)) {
    $RestoreString = $Inputstring.Substring($Inputstring.IndexOf(“(“)+1,($Inputstring.IndexOf(“)”)-($Inputstring.IndexOf(“(“)))-1)
    [integer]$RestoreSizeVal = $RestoreString.Substring(0,$RestoreString.IndexOf(” “))
    $RestoreSizeUnits = $RestoreString.Substring($RestoreString.IndexOf(” “)+1)
    $RestoreSizeKB = switch ($RestoreSizeUnits) {
    “MB” {[int]$RestoreSizeVal * 1024}
    “GB” {[int]$RestoreSizeVal * 1024 * 1024}
    “TB” {[int]$RestoreSizeVal * 1024*1024*1024}
    “PB” {[int]$RestoreSizeVal * 1024*1024*1024*1024}
    default {[int]$RestoreSizeVal}
    }
    } else
    { $RestoreSizeKB = 0
    }
    }
    $RestoreInfo.NbrofFiles = $NbrOfFiles
    $RestoreInfo.RestoreSizeKB = $RestoreSizeKB
    Return $RestoreInfo
    }
    $Backups = Get-VBRBackup -Name “Backup Job ERNIEB-PC”
    #$ernie = $Backups.sm # Info
    #$ernie

    $Jobs = Get-VBRJob -WarningAction SilentlyContinue

    foreach ($job in $Jobs) {
    $BackupSessionsList = @(Get-VBRBackupSession | ? {($_.CreationTime -ge (Get-Date).AddHours(-$LookBackHrs)) -and $_.JobName -eq $job.Name}) #-and $_.Status -ne “Success”
    $RestoreSessionsList = @(Get-VBRRestoreSession | ? {($_.CreationTime -ge (Get-Date).AddHours(-$LookBackHrs)) }) #-and $_.JobName -eq $job.Name}) #-and $_.Status -ne “Success”
    $BackupEPSessionsList = @(Get-VBREPSession | ? {($_.CreationTime -ge (Get-Date).AddHours(-$LookBackHrs)) }) # -and $_.JobName -eq $job.Name})

    #$BackupEPSessionsList
    #
    foreach ($tasks in $BackupSessionsList) {
    $task = Get-VBRTaskSession $tasks
    #[string]$JobIDstring=””
    #$JobID=””
    #$JobIDstring = $task.Id
    #$JobIDstring = $task.Id
    #$JobID = Convert-HEXtoDEC $JobIDstring

    $backuparray = $task | Select-Object @{Name=”VendorName”;Expression={$Vendor}},

    @{Name=”ClientName”; Expression = {“‘”+$_.Name+”‘”}},
    @{Name=”ClientIPAddress”; Expression = {$nullstrg}},
    #@{Name=”VendorJobType”; Expression = {“‘”+$job.JobType+”‘”}},
    @{Name=”VendorJobType”; Expression = {“‘BACKUP'”}},
    #@{Name=”JobStatus”; Expression = {$job.JobStatus}},
    #@{Name=”Long Job Name”;Expression={$tasks.Name}},
    #@{Name=”Job Level”;Expression={$tasks.Name.Substring(($tasks.Name.IndexOf(“(“))+1,($tasks.Name.IndexOf(“)”)-($tasks.Name.IndexOf(“(“)))-1)}},
    @{Name=”StartDateString”; Expression = {“‘”+$_.Progress.StartTime.ToString(“yyyy-MM-dd HH:mm:ss”)+”‘”}},
    @{Name=”FinishDateString”; Expression = {“‘”+$_.Progress.StopTime.ToString(“yyyy-MM-dd HH:mm:ss”)+”‘”}},
    @{Name=”BackupKilobytes”; Expression = {[math]::Round(($_.Progress.ReadSize/1024),1)}},
    #@{Name=”TransferedSize in KB”; Expression = {[math]::Round(($_.Progress.TransferedSize/1024),1)}},
    @{Name=”NbrOfFiles”; Expression = {$_.Progress.ProcessedObjects}},
    @{Name=”MediaType”; Expression = {“‘D'”}},
    #Status,
    @{Name=”VendorStatus”; Expression = {switch ($_.Status) {
    “Success” {0}
    “Failed” {2}
    default {1}
    }
    }},
    @{Name=”VendorJobID”; Expression = {“‘”+$_.Id+”‘”}},
    #@{Name=”VendorJobID”; Expression = {(“‘”+(Convert-HEXtoDECRes $_.Id)+”‘”) }},
    #@{Name=”VendorJobID3″; Expression = { “‘”+$JobIDstring+”‘” }},
    @{Name=”VendorPolicyName”; Expression={“‘”+$_.JobName+”‘”}},
    @{Name=”JobLevel”; Expression={“‘”+$_.Info.WorkDetails.TaskAlgorithm+”‘”}},
    #@{Name=”JobLevelSession”;Expression={ $_.JobSess.SessionInfo.SessionAlgorithm}},
    @{Name=”TargetName”;Expression={“‘”+$_.JobSess.JobSourceType+”‘”}},
    @{Name=”Schedule”; Expression = {“‘”+$_.Schedule+”‘”}}#,

    # @{Name=”Details”; Expression = {
    # If ($tasks.GetDetails() -eq “”){“‘”+($tasks.GetDetails()).Replace(“`n”,” “).Replace(“”,” – “) + ($tasks | Get-VBRTaskSession | %{If ($tasks.GetDetails()){$tasks.Name + “: ” + $tasks.GetDetails()}})+”‘”}
    # Else {(“‘”+$tasks.GetDetails()).Replace(“`n”,” “).Replace(“”,” – “)+”‘”}}} #| Format-Table #| ConvertTo-csv | % {$_ -replace ‘”‘,””} #-auto
    $outarray = $outarray + $backuparray
    }

    foreach ($EPtasks in $BackupEPSessionsList) {
    [string]$backupepstring=””
    #$EPtasks.sm
    #$backupepstring = $Job.Logger.GetLog() #.UpdatedRecords #| Select-Object title
    #$backupepstring
    #$EPtask = Get-VBREPTaskSession $EPtasks
    #write-hosts (‘$EPTask =’ + $EPtask)
    #[string]$JobIDstring=””
    #$JobID=””
    #$JobIDstring = $task.Id
    #$JobIDstring = $task.Id
    #$JobID = Convert-HEXtoDEC $JobIDstring

    $EPJob=””
    $EPRestorePoint = Get-VBRRestorePoint | ? {($_.CreationTime -ge ($EPtasks.CreationTime) -and $_.CreationTime -le ($EPtasks.EndTime)) }
    $EPJob = Get-VBREPJob -Id $EPRestorePoint.FindSourceJob().Id
    #write-host (‘Object Count = ‘ + $EPJob.ObjectsCount)
    #$EPRestorePoint
    $backupEParray = $EPtasks | Select-Object @{Name=”VendorName”;Expression={$Vendor}},

    @{Name=”ClientName”; Expression = {“‘”+$EPRestorePoint.fqdn+”‘”}},
    @{Name=”ClientIPAddress”; Expression = {$nullstrg}},
    #@{Name=”VendorJobType”; Expression = {“‘”+$job.JobType+”‘”}},
    @{Name=”VendorJobType”; Expression = {“‘BACKUP'”}},
    #@{Name=”JobStatus”; Expression = {$job.JobStatus}},
    #@{Name=”Long Job Name”;Expression={$tasks.Name}},
    #@{Name=”Job Level”;Expression={$tasks.Name.Substring(($tasks.Name.IndexOf(“(“))+1,($tasks.Name.IndexOf(“)”)-($tasks.Name.IndexOf(“(“)))-1)}},
    @{Name=”StartDateString”; Expression = {“‘”+$_.CreationTime.ToString(“yyyy-MM-dd HH:mm:ss”)+”‘”}},
    @{Name=”FinishDateString”; Expression = {“‘”+$_.EndTime.ToString(“yyyy-MM-dd HH:mm:ss”)+”‘”}},
    @{Name=”BackupKilobytes”; Expression = {[math]::Round(($EPRestorePoint.GetStorage().Stats.DataSize/1024),1)}},
    #@{Name=”TransferedSize in KB”; Expression = {[math]::Round(($_.Progress.TransferedSize/1024),1)}},
    @{Name=”NbrOfFiles”; Expression = {$EPJob.ObjectsCount}},
    @{Name=”MediaType”; Expression = {“‘D'”}},
    #Status,
    @{Name=”VendorStatus”; Expression = {switch ($_.Result) {
    “Success” {0}
    “Failed” {2}
    default {1}
    }
    }},
    @{Name=”VendorJobID”; Expression = {“‘”+$_.Id+”‘”}},
    #@{Name=”VendorJobID”; Expression = {(“‘”+(Convert-HEXtoDECRes $_.Id)+”‘”) }},
    #@{Name=”VendorJobID3″; Expression = { “‘”+$JobIDstring+”‘” }},
    @{Name=”VendorPolicyName”; Expression={“‘”+$EPRestorePoint.Name+”‘”}},
    @{Name=”JobLevel”; Expression={“‘”+$EPRestorePoint.Type+”‘”}},
    #@{Name=”JobLevelSession”;Expression={ $_.JobSess.SessionInfo.SessionAlgorithm}},
    @{Name=”TargetName”;Expression={“‘”+$EPRestorePoint.FindBackup().DirPath+”‘”}},
    @{Name=”Schedule”; Expression = {“‘”+$EPRestorePoint.FindBackup().TypeToString+”‘”}}#,

    # @{Name=”Details”; Expression = {
    # If ($tasks.GetDetails() -eq “”){“‘”+($tasks.GetDetails()).Replace(“`n”,” “).Replace(“”,” – “) + ($tasks | Get-VBRTaskSession | %{If ($tasks.GetDetails()){$tasks.Name + “: ” + $tasks.GetDetails()}})+”‘”}
    # Else {(“‘”+$tasks.GetDetails()).Replace(“`n”,” “).Replace(“”,” – “)+”‘”}}} #| Format-Table #| ConvertTo-csv | % {$_ -replace ‘”‘,””} #-auto
    $outarray = $outarray + $backupEParray
    }

    foreach ($restores in $RestoreSessionsList) {
    [string]$restorestring=””
    #[string]$JobIDstring=””
    #$RestoreJobIDs=””
    #$JobIDInteger=””

    $RestoreInfoDetails=””
    $restorestring = $restores.Logger.GetLog().UpdatedRecords | where-object {$_.title.Contains(“files to restore”)} | Select-Object title
    #$JobIDstring = $restores.ID
    #$RestoreJobID = Convert-HEXtoDECRes $JobIDstring
    $RestoreInfoDetails = Get-RestoreSize $restorestring
    #$RestoreInfoDetails.RestoreSizeKB
    #$RestoreInfoDetails.NbrofFiles
    $restorearray = $restores | Sort CreationTime | Select @{Name=”VendorName”;Expression={$Vendor}},
    @{Name=”ClientName”; Expression = {“‘”+$restores.Info.VmDisplayName+”‘”}},
    @{Name=”ClientIPAddress”; Expression = {$nullstrg}},
    @{Name=”VendorJobType”; Expression = {“‘RESTORE'”}},
    @{Name=”VendorPolicyName”; Expression={“‘”+$restores.Info.JobName+”‘”}},
    @{Name=”StartDateString”; Expression = {“‘”+$_.CreationTime.ToString(“yyyy-MM-dd HH:mm:ss”)+”‘”}},
    @{Name=”FinishDateString”; Expression = {“‘”+$_.EndTime.ToString(“yyyy-MM-dd HH:mm:ss”)+”‘”}},
    @{Name=”BackupKilobytes”; Expression = {$RestoreInfoDetails.RestoreSizeKB}},
    @{Name=”NbrOfFiles”; Expression = {$RestoreInfoDetails.NbrofFiles}},
    @{Name=”MediaType”; Expression = {“‘D'”}},
    #@{Name=”Duration (Mins)”; Expression = {[Math]::Round((New-TimeSpan $_.CreationTime $_.EndTime).TotalMinutes,2)}},
    @{Name=”VendorStatus”; Expression = {switch ($_.Info.Result) {
    “Success” {0}
    “Failed” {2}
    default {1}
    } }},
    @{Name=”VendorJobID”; Expression = {“‘”+$_.Id+”‘”}},
    #@{Name=”VendorJobID3″; Expression = {(“‘”+$RestoreJobID+”‘”)}},
    #@{Name=”VendorJobID”; Expression = {(“‘”+(Convert-HEXtoDECRes $_.Id)+”‘”)}},
    @{Name=”JobLevel”; Expression = {“‘”+$_.JobTypeString+”‘”}},
    @{Name=”TargetName”; Expression = {“‘”+$restores.Info.VmDisplayName+”‘”}},
    @{Name=”Schedule”; Expression = {“‘”+$_.Info.Initiator.Name+”‘”}},
    @{Name=”Details”; Expression = {“‘”+$_.Info.Reason+”‘”}}
    #@{Name=”Result”; Expression = {$_.Info.Result}} #| Format-Table -auto
    $outarray = $outarray + $restorearray
    }
    }
    # $outarray | ConvertTo-csv -NoTypeInformation | select -Skip 1 |% {$_ -replace ‘”‘,”} #| Out-File $outFile -Encoding utf8
    # $outarray | ConvertTo-csv -NoTypeInformation | select -Skip 1 |% {$_ -replace ‘”‘,”} | {switch ($outFile) {“” {} default {Out-File $outFile -Encoding utf8}}}

    If ($outFile ) {
    $outarray | ConvertTo-csv -NoTypeInformation | select -Skip 1 |% {$_ -replace ‘”‘,”} | Out-File $outFile -Encoding utf8
    }
    else
    {
    $outFile
    $outarray | ConvertTo-csv -NoTypeInformation | select -Skip 1 |% {$_ -replace ‘”‘,”} #| Out-File $outFile -Encoding utf8
    }

    Reply
  3. John Quinn

    Is there a way to encrypt the password in a file and then call that file from the powershell script, instead of stuffing the password in the file in clear text?

    Reply
    1. smasterson Post author

      I’m guessing you are talking about the email credentials? Certainly can be done, I typically run the script under an account that has privileges to the SMTP server and therefore neither the username or pwd get hard coded.

      You should be able to find plenty of examples of what you are looking for on the web.

      Reply
      1. john quinn

        Actually I was referring to veeam server account and password (and veeam server IP) that is required in the script to access the backups and create the report.

      2. smasterson Post author

        Hmmm, then you have me confused as the script does not hold the VBR u/p – it could, and could save this info to a file, but the assumption is that you would be running the script as a user with permissions, else some code would need to be added.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s