Monitoring and reporting for Veeam Data Platform
Post Reply
mtellier
Influencer
Posts: 15
Liked: 22 times
Joined: Feb 18, 2016 3:56 pm
Full Name: Mark Tellier
Contact:

Veeam ONE RESTFul Tutorial with PowerShell

Post by mtellier » 5 people like this post

Veeam ONE has a new RESTFul API that Jorge brought to our attention with his colorful integration with Grafana link to Grafana Dashboard for Veeam ONE v11

I was then motivated to test this API using PowerShell and would like to share what I've learned.
This script is also available on Github with plenty of documentation. link to Github

Please share your thoughts and any ideas you may have for improvements.

Code: Select all

<#
    4/12/2021
    Mark Telier

    Veeam ONE 11 RESTFul API Tutorial
    Demonstrate connecting to API and pulling data
#>

function Connect-VeeamAPI {
    [CmdletBinding()]
    param (
        [string] $AppUri,
        [pscredential] $Cred
    )

    begin {
        $header = @{
            "Content-Type" = "application/x-www-form-urlencoded"
            "accept" = "application/json"
        }
        
        $body = @{
            "grant_type" = "password"
            "username" = $cred.UserName 
            "password" = $cred.GetNetworkCredential().password
            "refresh_token" = " "
            "rememberMe" = " "
        }

        $requestURI = $veeamAPI + $appUri

        $tokenRequest = Invoke-RestMethod -Uri $requestURI -Headers $header -Body $body -Method Post -Verbose
        Write-Output $tokenRequest.access_token
    }
    
}

function Get-VeeamAPI {
    [CmdletBinding()]
    param (
        [string] $AppUri,
        [string] $Token
    )

    begin {
        $header = @{
            "accept" = "application/json"
            "Authorization" = "Bearer $Token"
        }

        $requestURI = $veeamAPI + $AppUri
        $results = Invoke-RestMethod -Method GET -Uri $requestUri -Headers $header
        
        Write-Output $results
    }
    
}

# ---------- DEFINE VARIABLES ---------- #
$veeamAPI = "https://veeamone.acme.com:1239"
$cred = Get-Credential -Message "Veeam One Credentials" -UserName "ACME\username"

# ignore self signed certificate or request failS
add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
    public bool CheckValidationResult(
        ServicePoint srvPoint, X509Certificate certificate,
        WebRequest request, int certificateProblem) {
        return true;
    }
}
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

# ---------- REQUEST TOKEN ---------- #
$appURI = "/api/token"
$token = Connect-VeeamAPI -AppUri $appURI -Cred $cred

# ---------- REQUEST ABOUT ---------- #
$appURI = "/api/v1/about"
Get-VeeamAPI -AppUri $appURI -Token $token

# ---------- REQUEST INSTALLATION INFO ---------- #
$appURI = "/api/v1/about/installationInfo"
Get-VeeamAPI -AppUri $appURI -Token $token

# ---------- REQUEST LICENSE ---------- #
$appURI = "/api/v1/license"
Get-VeeamAPI -AppUri $appURI -Token $token

# ---------- REQUEST CURRENT USAGE ---------- #
$appURI = "/api/v1/license/currentUsage"
Get-VeeamAPI -AppUri $appURI -Token $token

# ---------- REQUEST DASHBOARDS ---------- #
$appURI = "/api/v1/dashboards"
Get-VeeamAPI -AppUri $appURI -Token $token


#################################################
# ---------- WIDGET RESOURCE EXAMPLE ---------- #
#################################################
$appURI = "/api/v1/dashboards"

# get all dashboards
$dashboards = Get-VeeamAPI -AppUri $appURI -Token $token

# select dashboard ids
$vbrDashID = ( $dashboards | Where-Object -Property "Name" -Like "Veeam Backup and Replication" ).dashboardId
$vsphereTrendDashID = ($dashboards | Where-Object -Property "Name" -Like "vSphere Trends").dashboardId
$vsphereAlarmDashID = ($dashboards | Where-Object -Property "Name" -Like "vSphere Alarms").dashboardId
$vsphereHostDashID = ($dashboards | Where-Object -Property "Name" -Like "vSphere Hosts and Clusters").dashboardId
$vsphereDatastoreDashID = ($dashboards | Where-Object -Property "Name" -Like "vSphere Datastores").dashboardId
$vsphereVMDashID = ($dashboards | Where-Object -Property "Name" -Like "vSphere VMs").dashboardId
$vsphereInfraDashID = ($dashboards | Where-Object -Property "Name" -Like "vSphere Infrastructure").dashboardId

# get VBR dashboard
# $appURI = "/api/v1/dashboards/1"
$appURI = $appURI + "/$vbrDashID"

$vbrDash = Get-VeeamAPI -AppUri $appURI -Token $token

# select widgets
$vbrWidgets = $vbrDash.dashboardWidgets

# select widget ids
$infraWidgetID = ($vbrWidgets | Where-Object -Property "Caption" -Like "Backup Infrastructure Inventory").widgetId
$vmsWidgetID = ($vbrWidgets | Where-Object -Property "Caption" -Like "Backup Infrastructure Inventory").widgetId
$windowWidgetID = ($vbrWidgets | Where-Object -Property "Caption" -Like "Backup Window").widgetId
$topJobWidgetID = ($vbrWidgets | Where-Object -Property "Caption" -Like "Top Jobs by Duration").widgetId
$jobStatsWidgetID = ($vbrWidgets | Where-Object -Property "Caption" -Like "Jobs Status").widgetId
$topRepoWidgetID = ($vbrWidgets | Where-Object -Property "Caption" -Like "Top Repositories by Used Space").widgetId

# get Backup Infrastructure Inventory Widget
# $appURI = "/api/v1/dashboards/1/widgets/1"
$appURI = $appURI + "/widgets/$infraWidgetID"
$infraWidget = Get-VeeamAPI -AppUri $appURI -Token $token

# get BackupAlarmsOverview ???
# $appURI = "/api/v1/dashboards/1/widgets/1/datasources"
$appURI = $appURI + "/datasources"
$infraWidget = Get-VeeamAPI -AppUri $appURI -Token $token

# select ID
$infraWidgetID = $infraWidget.datasourceId

# get Backup Infrastructure Inventory
# $appURI = "/api/v1/dashboards/1/widgets/1/datasources/58/data?forceRefresh=false"
$appURI = $appURI + "/$infraWidgetID/data?forceRefresh=false"
$infraData = Get-VeeamAPI -AppUri $appURI -Token $token

# We finally have our data
$infraData.data | Format-Table

# Tidy up the output
$infraData.data
$report = @()

foreach ($item in $infraData.data) {
    $props = [ordered]@{
        "Object"   = ($item.name -replace "\(.*\)").TrimEnd()
        "Ok"       = $item.noAlarms
        "Warning"  = $item.warnings
        "Error"    = $item.errors
    }

    $report += New-Object -TypeName psobject -Property $props
}
$report

# Wrap it in HTML
$outFile = "C:\Temp\VeeamONEReport.html"
$Header = @"
<style>
table {
    font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
    border-collapse: collapse;
    width: 100%;
}
th {
    padding-top: 12px;
    padding-bottom: 12px;
    text-align: left;
    background-color: #4CAF50;
    color: white;
}
</style>
<title>Report Title</title>
"@

$htmlReport = $report | ConvertTo-Html -Fragment
ConvertTo-Html -Body $htmlReport -Head $Header | Out-File $outFile
Invoke-Item $outFile

# Send to an inbox
$htmlBody = ConvertTo-Html -Body $htmlReport -Head $Header | Out-String
$message = @{
    To         = 'roadrunner@acme.com'
    From       = 'postmaster@acme.com'
    Subject    = 'Test Report'
    Body       = $htmlBody
    SmtpServer = 'emailserver.acme.com'
}

Send-MailMessage -BodyAsHtml @message
HannesK
Product Manager
Posts: 15627
Liked: 3453 times
Joined: Sep 01, 2014 11:46 am
Full Name: Hannes Kasparick
Location: Austria
Contact:

Re: Veeam ONE RESTFul Tutorial with PowerShell

Post by HannesK »

Hello Mark,
thanks for sharing your experience with the community 👍

Best regards,
Hannes
matteu
Veeam Legend
Posts: 895
Liked: 141 times
Joined: May 11, 2018 8:42 am
Contact:

Re: Veeam ONE RESTFul Tutorial with PowerShell

Post by matteu »

Hello,

I know this is an old thread but I'm trying to use Powershell and Rest API on v13 and this script is a good start.
I updated it to replace v1 to v2.3 but it doesn't work because of widget URL.

I would like to know if it's possible or not to use them ? I don't find anything in the documentation about the URL and totally ignore how I can find them.

I mean, the script works fine until line 139.

On 140, the query is trying to reach the following URL : /api/v2.3/dashboards/1/widgets/1/datasources/58/data?forceRefresh=false
However it doesn't work and display "Method not allowed".

How could I find what is wrong here ? There is nothing I can find on the documentation on the /api/v2.3/dashboards/XXXXXXXX

Thanks
jorgedlcruz
Veeam Software
Posts: 1733
Liked: 757 times
Joined: Jul 17, 2015 6:54 pm
Full Name: Jorge de la Cruz
Contact:

Re: Veeam ONE RESTFul Tutorial with PowerShell

Post by jorgedlcruz »

Hello Matteu,
I would strongly recommend using official RestAPI endpoints that you can find here, and visually in a map here.

But, if you like cutting-edge material, I just updated the script to collect even Threat Center, etc.

The problem with the initial script of this thread, or this latest one, is that it is using POST, and the VONE internal API, that might vary depending of VONE installations, etc. I tried to make it agnostic as much as possible, give it a try.

Curious to understand what is the data that you need out of Veeam ONE :) as there is one more script that uses supported APIs that takes data out of supported APIs. And once added to Grafana looks super cool, perfect for seeing current state.

Image

Image

Keen to understand, thanks!
Jorge de la Cruz
Director Observability & AI Product Management | Veeam ONE @ Veeam Software

@jorgedlcruz
https://www.jorgedelacruz.es / https://jorgedelacruz.uk
vExpert 2014-2025 / InfluxAce / Grafana Champion
matteu
Veeam Legend
Posts: 895
Liked: 141 times
Joined: May 11, 2018 8:42 am
Contact:

Re: Veeam ONE RESTFul Tutorial with PowerShell

Post by matteu »

Hello,
Thanks for the complete answer.
Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests