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.
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:
- Veeam Availability Orchestrator setup – pt.1
- Veeam Availability Orchestrator configure a Failover Plan – pt.2
- Step by Step Guide Veeam Availability Orchestrator Install
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:
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.
I have exported my optimized Postman Collection into the GitHub Repository of the project.
Create PowerShell Module
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.
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.
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.
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.
Documentation of the function: Set-VaoFailoverPlan