For your reference, here are the articles in this mini-series:

Introduction

Following on from the previous article in this mini-series, this article demonstrates how to retrieve a generated report from vROps as a PowerShell object.

Downloading A Generated Report

The last step of the previous article was to use the GetReport() method to verify that your report generation was complete.

$vrops.ExtensionData.GetReport("5ef2e8c9-09bb-4a74-b560-f9ad2e810854")

Name               :
Description        : Oversized VMs Report.
ResourceId         : 26717f44-cd8d-486a-821f-e1df41bb49b3
ReportDefinitionId : 1f69952f-7ff4-4d2c-9446-81a811de19b0
TraversalSpec      :
Subject            : VirtualMachine VirtualMachine
Owner              : f315d79d-72ac-46ff-a512-cb43073246c3
CompletionTime     : Wed May 16 12:07:50 BST 2018
Status             : COMPLETED
Links              : {linkToSelf, linkToResource, linkToReportDefinition}
Any                :
Id                 : 5ef2e8c9-09bb-4a74-b560-f9ad2e810854
AnyAttr    

Let's take a look at the properties and methods of the GetReport() method using the Get-Member cmdlet.

$vrops.ExtensionData.GetReport("5ef2e8c9-09bb-4a74-b560-f9ad2e810854") | Get-Member

   TypeName: VMware.VimAutomation.VROps.Views.Report

Name                MemberType Definition
----                ---------- ----------
DownloadReport      Method     void DownloadReport(System.IO.Stream outputStream, string format)
DownloadReportAsync Method     System.Threading.Tasks.Task DownloadReportAsync(System.Threading.CancellationToken cancellationToken, System.IO.Stream outputStream, string format), System.Threading.Tasks.T...
Equals              Method     bool Equals(System.Object obj)
GetHashCode         Method     int GetHashCode()
GetType             Method     type GetType()
ToString            Method     string ToString()
Any                 Property   System.Xml.XmlElement[] Any {get;set;}
AnyAttr             Property   System.Xml.XmlAttribute[] AnyAttr {get;set;}
CompletionTime      Property   string CompletionTime {get;set;}
Description         Property   string Description {get;set;}
Id                  Property   string Id {get;set;}
Links               Property   VMware.VimAutomation.VROps.Views.LinkTag[] Links {get;set;}
Name                Property   string Name {get;set;}
Owner               Property   string Owner {get;set;}
ReportDefinitionId  Property   string ReportDefinitionId {get;set;}
ResourceId          Property   string ResourceId {get;set;}
Status              Property   string Status {get;set;}
Subject             Property   string Subject {get;set;}
TraversalSpec       Property   VMware.VimAutomation.VROps.Views.TraversalSpec TraversalSpec {get;set;}

Right at the top of that list is DownloadReport(), which is the method that we are after. To see which properties the DownloadReport() method expects as its inputs, we can call the method on its own.

$vrops.ExtensionData.GetReport("5ef2e8c9-09bb-4a74-b560-f9ad2e810854").DownloadReport

OverloadDefinitions
-------------------
void DownloadReport(System.IO.Stream outputStream, string format)

This tells us that it requires two inputs: (1) a System.IO.Stream object; and (2) a string specifying the format in which to download the report. The API documentation states that the format can be either PDF or CSV. If not specified, the default is PDF. Given that we are trying to convert this report into a PowerShell object, a PDF is useless to us; therefore, we need to make sure that we specify CSV.

First, we will create a System.IO.Stream object. The .NET API documentation for the System.IO namespace helpfully lists the available stream classes. We'll be using the MemoryStream class. You can create a MemoryStream object in PowerShell as follows:

$MemoryStream = New-Object System.IO.MemoryStream

Now we run the DownloadReport() method with the $MemoryStream object, making sure to specify CSV as the format.

$vrops.ExtensionData.GetReport("5ef2e8c9-09bb-4a74-b560-f9ad2e810854").DownloadReport($MemoryStream, "CSV")

Once we have received our report into the $MemoryStream object, we need to use a System.IO.StreamReader object to read the stream. But before we create this object, we need to set the current position of the $MemoryStream back to its starting point.

$MemoryStream.Seek(0, "Begin")
$ReadStream = New-Object System.IO.StreamReader($MemoryStream)

With the $ReadStream object populated with the $MemoryStream data, we can now loop through the $ReadStream line by line and write the data to the console.

while ($ReadStream.Peek() -ne -1) {
    $ReadStream.ReadLine()
}

I've used the Peek() method of the System.IO.StreamReader object to identify the end of the stream (when it returns -1). Again, the .NET API documentation is a great resource to find these methods and to see how they can be used.

Hopefully, each line of your report has been written to your PowerShell console, which is great. So, to convert this data into a PowerShell object, we will first store it as a string.

while ($ReadStream.Peek() -ne -1) {
    $Output += $ReadStream.ReadLine()
    $Output += "`n"
}

With this slight tweak of the while loop, we are now appending each line from the $ReadStream object to a new $Output object, which is a string. Because this is a string you will notice that I am having to tell it where to break for a new line with `n, which is the PowerShell special character for 'new line'.

We now have our report, represented as a string of CSV data, stored in the $Output object. This makes it very easy to convert this string of data into a PowerShell object using the ConvertFrom-Csv cmdlet!

$Output | ConvertFrom-Csv

And there you have it: your vROps report is now a PowerShell object.

Next Steps

The first two articles in this mini-series have hopefully shown you how to use the vROps API, together with PowerCLI to generate and download reports as a PowerShell object. However, I appreciate that it is quite a long and cumbersome process. This is why I have been working on a helper module, which will tie together all of the steps from these articles into easy-to-use cmdlets. Check back for part 3 where I will show you the module and how you can download it.