PowerShell Module for Veeam Availability Orchestrator

As a VMware Site Recovery Manager enthusiast I was very interested in the new Veeam Availability Orchestrator. And finally I found the time to deploy and configure the new rising start in the Veeam Software portfolio. Even in version 1.0 the Veeam Availability Orchestrator is already a great product and will help a lot of customers to create a reliable Disaster Recovery concept. During my configuration process I was wondering that there is no PowerShell Module for Veeam Availability Orchestrator available. But wait there is an API, so I started to create my own PowerShell Module.

Veeam has done a great job with the API Implementation. There is a great documentation and even a Swagger interface available.

PowerShell Module for Veeam Availability Orchestrator - Swagger

If you are interested in detail about installation and configuration of Veeam Availability Orchestrator I would recommend some great blog posts from my Veeam Vanguard fellows:

Creating a PowerShell Module for Veeam Availability Orchestrator

If a well-documented RESTFul API is available it is not very complex to get started with the right Tools. One of the most important Tools for me while working with RESTFul API is Postman.

Understand and verify the API calls

Before I start working on the PowerShell Module i try to understand the API and verify the calls i want to use in my PowerShell Module. Postman has also the capability to import Swagger File into a collection (Url: https://<VAO FQDN>:9899/swagger/docs/v1). After the Import only a few optimizations need to done:

  • Handle Authentication

Postman can run scripts after the API Call (tests). You can use these scripts to extract data from the response and write it to the Environment. These filled  variables can then be used in further API calls. In case of the Veeam Availablity Orchestrator API we need the tokens:

PowerShell Module for Veeam Availability Orchestrator - Postman test

var body = JSON.parse(responseBody)
pm.environment.set("refresh_token", body.refresh_token);
pm.environment.set("access_token", body.access_token);
  • Set variables

To be more flexible it is a common practice in postman to work with variables in call Url, Header and Body.

PowerShell Module for Veeam Availability Orchestrator - Postman Variables

I have exported my optimized Postman Collection into the GitHub Repository of the project.

Create PowerShell Module

Disclaimer:

What I am sharing here is just my practice to create a RESTFul API PowerShell Module and not the Best Practice to do this. There are way better modules available to show how to do is more efficient (e.g. VMware PowerNSX).

When I start building a RESTFul API based PowerShell Module I try to create two main initial functions, a function to connect to the API and another function as a helper for the general API calls. The connection function should also store the connection details, used by the general API call function. All further functions for application specific calls are based on the general API call function.

Connection function

Veeam Availability Orchestrator API authorization process is based on the OAuth 2.0 Authorization Framework.

More Details: Veeam Availability Orchestrator 1.0 RESTful API Reference – Authorization and Security

#region: Workaround for SelfSigned Cert and force TLS 1.2
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
[System.Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
#endregion
Function New-VaoApiConnection {
    <#
    .DESCRIPTION
        Connecto to Veeam Availability Orchestrator API.

    .NOTES
        File Name  : New-VaoApiConnectionl.psm1
        Author     : Markus Kraus
        Version    : 1.0
        State      : Ready

    .LINK
        https://mycloudrevolution.com/

    .LINK
        https://helpcenter.veeam.com/docs/vao/restapi/overview.html?ver=10

    .EXAMPLE
        $YourCredentials = Get-Credential
        New-VaoApiConnection -Server "vao01.lab.local" -Credential $YourCredentials

    .PARAMETER Server
        FQDN of the Veeam Availability Orchestrator Instance

    .PARAMETER Token
        Existing Token for renewal (not yet implemented)

    .PARAMETER Credential
        Credential for the Veeam Availability Orchestrator Instance

    #>
        Param (
            [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="FQDN of the Veeam Availability Orchestrator Instance")]
            [ValidateNotNullorEmpty()]
                [String]$Server,
            [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage="Existing Token for renewal (not yet implemented)")]
            [ValidateNotNullorEmpty()]
                [String]$Token = $Global:VaoApiConnection.Token,
            [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Credential for the Veeam Availability Orchestrator Instance")]
            [ValidateNotNullorEmpty()]
                [Management.Automation.PSCredential]$Credential
        )
        Process {
            try {
                $FullUri = "https://" + $Server + ":9899" +  "/v1/About"
                $Headers =  @{'Accept' = 'application/json, text/json, text/html, application/xml, text/xml'}
                $Return = Invoke-RestMethod -uri $FullUri -Method Get -Headers $Headers
            }
            catch {
                Throw "Failed to contact Veeam Availability Orchestrator API. Login aborted!"
            }

            $username = $Credential.UserName
            $password = $Credential.GetNetworkCredential().Password

            $FullUri = "https://" + $Server + ":9899" +  "/v1/Accounts/Token"
            $Headers =  @{'Content-Type' = 'application/x-www-form-urlencoded'}
            $Body = @{      grant_type = 'password';
                            username = $username;
                            password = $password;
                            refresh_token = $Token
                    }
            $Return = Invoke-RestMethod -uri $FullUri -Method POST -Headers $Headers -Body $Body

            #region: Cleanup Confidential Data
            Clear-Variable -Name username, password
            #endregion

            #region: Build Connection Variable
            $Global:VaoApiConnection = [pscustomobject]@{
                Server = $Server
                access_token = [String]$Return.access_token
                refresh_token = [String]$Return.refresh_token
                token_type = [String]$Return.token_type
            }
            #endregion

            $Global:VaoApiConnection
        }
    }

General API call function

The API call helper function uses per default the recommended headers for the Veeam Availability Orchestrator API endpoint. The header also includes the authentication token.

#region: Workaround for SelfSigned Cert and force TLS 1.2
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
[System.Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
#endregion
Function Invoke-VaoApiCall {
    <#
    .DESCRIPTION
        Helper function to call the Veeam Availability Orchestrator API.

    .NOTES
        File Name  : Invoke-VaoApiCall.psm1
        Author     : Markus Kraus
        Version    : 1.0
        State      : Ready
    .LINK
        https://mycloudrevolution.com/

    .LINK
        https://helpcenter.veeam.com/docs/vao/restapi/overview.html?ver=10

    .EXAMPLE
        Invoke-VaoApiCall -Uri "/v1/About" -Method Get

    .PARAMETER Server
        FQDN of the Veeam Availability Orchestrator Instance

    .PARAMETER Token
        Bearer Token for the Veeam Availability Orchestrator Instance

    .PARAMETER Uri
        API Uri for the Call

    .PARAMETER Accept
        Accept Header for the API Call

    .PARAMETER Methode
        Methode of the API Call

    .PARAMETER Body
        Body of the API Call

    #>
        Param (
            [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage="FQDN of the Veeam Availability Orchestrator Instance")]
            [ValidateNotNullorEmpty()]
                [String]$Server = $Global:VaoApiConnection.Server,
            [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage="Bearer Token for the Veeam Availability Orchestrator Instance")]
            [ValidateNotNullorEmpty()]
                [String]$Token = $Global:VaoApiConnection.access_token,
            [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="API Uri for the Call")]
            [ValidateNotNullorEmpty()]
                [String]$Uri,
            [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage="Accept Header for the API Call")]
            [ValidateNotNullorEmpty()]
                [String]$Accept = "application/json, text/json, text/html, application/xml, text/xml",
            [Parameter(Mandatory=$True, ValueFromPipeline=$False, HelpMessage="Method of the API Call")]
            [ValidateNotNullorEmpty()]
            [ValidateSet("Get","Post")]
                [String]$Method,
            [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage="Body of the API Call")]
            [ValidateNotNullorEmpty()]
                $Body
        )
        Process {
            $FullToken = "Bearer " + $Token
            #region: RESTful API Call
            if ($Method -like "Get" ) {
                $FullUri = "https://" + $Server + ":9899" +  $Uri
                $Headers =  @{'accept' = $Accept;'Authorization' = $FullToken}
                $Return = Invoke-RestMethod -uri $FullUri -Method $Method -Headers $Headers
            }
            elseif ($Method -like "Post") {
                if ($Body) {
                    $FullUri = "https://" + $Server + ":9899" +  $Uri
                    $Headers =  @{'accept' = $Accept;'Authorization' = $FullToken}
                    $Return = Invoke-RestMethod -uri $FullUri -Method $Method -Headers $Headers -Body $Body
                }
                else {
                    $FullUri = "https://" + $Server + ":9899" +  $Uri
                    $Headers =  @{'accept' = $Accept;'Authorization' = $FullToken}
                    $Return = Invoke-RestMethod -uri $FullUri -Method $Method -Headers $Headers
                }

            }
            #edregion

            $Return
        }
    }

Application specific function

This is an example of a function included in the PowerShell Module for Veeam Availability Orchestrator based on the general API call function. In line 32 and 35 (depending on input) the general API call function is called.

Function Get-VaoSite {
    <#
    .DESCRIPTION
        Get Veeam Availability Orchestrator Sites

    .NOTES
        File Name  : Get-VaoSite.psm1
        Author     : Markus Kraus
        Version    : 1.0
        State      : Ready

    .LINK
        https://mycloudrevolution.com/

    .EXAMPLE
        Get-VaoSite | Select-Object name, id, serverName, type | ft -AutoSize

    .EXAMPLE
        Get-VaoSite -SiteID 850316df-d73f-4e8b-b8bc-7b1815fb0a9e | Select-Object name, id, serverName, type | ft -AutoSize

    .PARAMETER SiteID
        Optional Veeam Availability Orchestrator Site ID

    #>
        Param (
            [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage="Optional Veeam Availability Orchestrator Site ID")]
            [ValidateNotNullorEmpty()]
                [String]$SiteID
        )
        Process {
            if ($SiteID) {
                $Return = Invoke-VaoApiCall -Uri "/v1/Sites/$SiteID" -Method Get
            }
            else {
                $Return = Invoke-VaoApiCall -Uri "/v1/Sites" -Method Get
            }

            $Return
        }
    }

PowerShell Module for Veeam Availability Orchestrator

New-VaoApiConnection

At first a connection to the Veeam Availability Orchestrator (VAO) instance needs to be established. The New-VaoApiConnection function authenticates with given credentials and saved the Authorization Token together with the environment details as a global variable for further use in other functions of the PowerShell Module for Veeam Availability Orchestrator.

The API can also refresh an existing token but this feature is not yet implemented.

PowerShell Module for Veeam Availability Orchestrator - New-VaoApiConnection

Documentation of the function: New-VaoApiConnection

Get-VaoSite

The Get-VaoSite function can be used to get a list of all registered VAO sites or to get a representation of a VAO site with the specified ID.

PowerShell Module for Veeam Availability Orchestrator - Get-VaoSite

Documentation of the function: Get-VaoSite

Properties:

Property Type Description
name string Name of a VAO site.
id string System ID assigned to a VAO site in Veeam Availability Orchestrator RESTful API.
serverName string Name of a machine on which a VAO site is registered.
contactName string Contact name of a person responsible for monitoring VAO performance.
contactEmail string Email of a person responsible for monitoring VAO performance.
contactTel string Telephone number of a person responsible for monitoring VAO performance.
description string Description of a VAO site.
type string Type of a VAO site.
_links dictionary of string [key] and object [value] Links to related resources (navigation property).

Source: https://helpcenter.veeam.com/docs/vao/restapi/sites_properties.html?ver=10

Get-VaoFailoverPlan

The Get-VaoFailoverPlan function can be used to get a list of all created failover plans or to get a list of all failover plans created for a VAO site with the specified ID.

PowerShell Module for Veeam Availability Orchestrator - Get-VaoFailoverPlan

Documentation of the function: Get-VaoFailoverPlan

Properties:

Property Type Description
name string Name of a failover plan.
id string System ID assigned to a failover plan in Veeam Availability Orchestrator RESTful API.
contactName string Contact name of a person responsible for monitoring VAO performance.
contactEmail string Contact email of a person responsible for monitoring VAO performance.
contactTel string Telephone number of a person responsible for monitoring VAO performance.
description string Description of a failover plan.
planState string Current state of a failover plan.
planStateDetails string Provides additional details on processing a failover plan and shows the number of errors and warnings occurred.
scheduleEnabled boolean Defines whether a failover plan has a configured schedule.
scheduleType string Defines whether a failover plan will run at specific time (OnTime) or right after another plan (AfterPlan).
scheduleAfter string System ID of a preceding failover plan.
scheduleAfterPlanName string Name of a preceding failover plan.
scheduleTime string Date and time when a failover plan will run.
siteId string System ID of a VAO site for which a failover plan is created.
_links dictionary of string [key] and object [value] Links to related resources (navigation property).

Source: https://helpcenter.veeam.com/docs/vao/restapi/failoverplans_properties.html?ver=10

Set-VaoFailoverPlan

The Set-VaoFailoverPlan can be used, in the version 1.0 of the module, to enable or disable the given Failover Plan.

The API has a lot of more Operations and Methods for Failover Plans. Maybe some of them will be implemented in future versions of the PowerShell Module for Veeam Availability Orchestrator.

PowerShell Module for Veeam Availability Orchestrator - Set-VaoFailoverPlan

Documentation of the function: Set-VaoFailoverPlan

Get the Module

PowerShell Gallery  Read The Docs  GitHub

Leave a Reply