Sergey Nivens - Fotolia

Get started Bring yourself up to speed with our introductory content.

Use APIs to create a custom disaster recovery report

The right set of PowerShell commands and API calls can go a long way to build and customize a disaster recovery report. Learn how with these steps.

A custom disaster recovery report can be helpful in the DR process, but creating one isn't simple. However, APIs -- a tool disaster recovery admins often overlook-- can ease the process.

Custom reports can deliver the status of a DR environment directly to an admin's inbox. They eliminate the need for manual checks to ensure everything runs smoothly. These reports are also a good option when an organization's DR provider does not offer a streamlined reporting feature or only does so as part of a higher payment tier.

This guide takes admins through the creation of a custom DR report step by step. Learn how to extract the necessary data, as well as how to use API endpoints to build the disaster recovery report.

This guide features Zerto and its DR API. However, the principles transfer to other vendor APIs, such as Veeam or Commvault. A rudimentary understanding of PowerShell is helpful to get the most out of this guide.

Get started

An API consists of a series of endpoints, or uniform resource identifiers (URIs), that enable programmatic access to software. Admins make a request and APIs return the appropriate data.

With Zerto as the example, use PowerShell and the API to create a code snippet to request a list of VMs:

$myURL = "https://myZertoServer.local:9669/vms"
$myVmArray = Invoke-RESTMethod -Method Get -Uri $myURL  -Headers $zertoHeader

The above will interrogate the URI specified in the Invoke-RESTMethod and put the returned data into the variable myVmArray. When we use the Invoke-RESTMethod, PowerShell will convert the returned XML from the API endpoint into a PowerShell array by default.

In this example, the method parameter specifies what we are doing with the information. The GET method is used to fetch data equates only.

The volume of potential items accessible via the API is massive. Admins, for example, can use APIs to gather data on datastores, networks and disk utilization. This aids in the creation of custom DR reports. First, however, we must ensure we are appropriately authorized to pull this data from the endpoint.

Headers contain authentication information required to access the API endpoints. They enable the use of an authorization string that is passed with each API request to prove users are who they say they are.

Below is an example of using headers with Zerto. Include the authentication header using the
-Headers portion of the PowerShell code snippet shown above.

Header requirements can vary wildly between platforms; they can be as simple as one line or super complex. Unfortunately, Zerto falls into the latter. The header posted below is taken from Zerto's own API documentation.

$ZertoServer = @("myzertoserver")
$ZertoPort = "9669"
$ZertoUser = "zertouser"
$ZertoPassword = "zertopassword"
<# Set the above to reflect your environment #>
$baseURL = "https://" + $ZertoHost + ":"+$ZertoPort+"/v1/"
$xZertoSessionURL = $baseURL + "session/add"
$authInfo = ("{0}:{1}" -f $ZertoUser,$ZertoPassword)
 $authInfo = [System.Text.Encoding]::UTF8.GetBytes($authInfo)
$authInfo = [System.Convert]::ToBase64String($authInfo)
$headers = @{Authorization=("Basic {0}" -f $authInfo)}
$sessionBody = '{"AuthenticationMethod": "1"}' 
$TypeJSON = "application/json"      
     Try
      {
        $xZertoSessionResponse = Invoke-WebRequest -Uri $xZertoSessionURL -Headers $headers -Method POST -Body $sessionBody -ContentType $TypeJSON
        }
Catch {
        Write-Host $_.Exception.ToString()
        $error[0] | Format-List -Force
  }
$xZertoSession = $xZertoSessionResponse.headers.get_item("x-zerto-session")
$zertoSessionHeader = @{"x-zerto-session"=$xZertoSession}

Edit the first four lines of the PowerShell script above to reflect your environment, call getxZertoSession and enter the username and password.

Each usage of the script creates a new session, granting access to the resources. Think of it as connecting or disconnecting from a service. The session start is found in the code above and put in the $zertoSessionHeader variable on the last line.

Use the API to get data

To create reports, use APIs to grab data.

Zerto provides the "alerts" endpoint that details all the errors and warnings for the Zerto site and any paired sites. The next step is to create a WebRequest compatible string to pass to the authenticated session.

Best practice suggests using a base URL that contains the URL, minus the endpoints. Then, when admins need to build a URL, they use the base URL and add on the endpoint. That said, the following string does not reflect best practices to build an endpoint, but is simplified for this example:

$myAlertsURL = "https://myZertoServer.local:9669/alerts"

Then, invoke the URL string:

$alertsData = Invoke-WebRequest -Method Get -URI $myAlertsURL -Header $zertoHeader

Once the script is run, assuming there are no errors, the entirety of the alerts and all the information about them is in $alertsData. Type in $alertsData to verify this and read the variable on the PowerShell command line.

Admins can experiment and pull other data, including site and bandwidth information. However, proceed with caution if you're using anything other than a GET method, as other changes can modify configurations.

Create and customize a report

Data in the variable $alertsData is nowhere near a full HTML report. Luckily, PowerShell has a cmdlet convertTo-Html, which exports the contents of a variable or object into a HTML report.  To use it in its simplest form, pipe the variable into the cmdlet as follows:

$alertsData | convertTo-Html | outputfile c:\myexample.html

In some cases, the DR admin may not want the report to include all available fields. Rather than create such a wide report, PowerShell has a select-Object cmdlet that admins can place between the commands to select only the desired fields, like this:

$alertsData | select-Object Level, TurnedOn, Description | convertTo-Html

Run $alertsData from the PowerShell command line to return all errors and show what data is available to select.

At this point, it is possible to write out the filtered details to an HTML file. The convertTo-Html cmdlet comes with many options. The following example would create a basic report:

$alertsData | select-Object Level, TurnedOn, Level, Description | convertToHTML '
-Body "Daily report $(get-date -Format "YYYY-mm-dd")$alertsData '
-OutputFile "DailyReport.html"

There are some new entries in the above code snippet. The -Body parameter represents any content admins want to include in the HTML <body> tag. The above will put DailyReport with the date, which can be formatted in various ways. Also, note the ' in the code snippet. This enables the split of a long command across several lines to enhance readability.

At this point, the data is exported to an HTML document.  Currently, the report will just spit out errors and warnings as it encounters them. To group by errors and warnings, use the Order-by cmdlets:

$alertsData | select-Object select-Object Level, TurnedOn, Description | Order-by TurnedOn | convertToHTML '
-Body "Daily report $(get-date -Format "YYYY-mm-dd")$alertsData '
-OutputFile "DailyReport.html"

As the report stands now, it has one table, but multiple tables are possible with convertTo-Html and the -Fragment property.  To further adjust the design and formatting of the report, use an inline style sheet, such as the one shown in this Adam the Automator blog post.

The default table headers are a bit poorly worded. There is no PowerShell cmdlet to fix this directly, but we can use a filter on the output before we write it out. Use the PSItem cmdlet. We can fit this in between convertTo-Html and outputting to the file:

ForEach-Object { $PSItem -replace"<th>TurnedOn</th>","<th>Alarm Activated</th>"}

The above bit of code will change the table header TurnedOn to the more descriptive Alarm Activated.

This Content Component encountered an error

SearchDataBackup

SearchStorage

SearchConvergedInfrastructure

Close