I’ve been looking for a good reason to try out the Aria Operations Management Pack Builder, ever since a peer of mine built one for Pi-Hole back in early 2023. One thing that I thought would be of particular interest was tracking the power consumption of my lab. This article will outline how I achieved this goal.
Getting the data
The first task for this project was finding a way to get the data on my power consumption. The majority of my lab gear plugs into a small APC BackUPS UPS, which provides enough power to handle the occasional blip, but not to run the lab for any meaningful amount of time. This UPS came with a serial/USB cable that could be managed with some software available for Windows. I don’t have a physical Windows system running 24×7 in my lab, but I do have a domain controller virtual machine that resides on local disk of a single system. Since the VM isn’t moving around with DRS, I was able to pass a USB device through to the VM. I added a new USB controller, then added a new USB device, and then my VM settings had the following entries:
With this USB device passed through to the VM, I was able to install the PowerChute Serial Shutdown application. In this application, there is a logging > data log configuration, where you can set how frequently the service should record data. I’ve set this to 5 minutes. With this configuration enabled, there is a text file that is updated in this folder: C:\Program Files\APC\PowerChute Serial Shutdown\agent\energylog
that includes details on the relative load in percentage of the UPS as well as the calculated load in watts. This is a great start, we now have a source of data on our local filesystem.
Formatting the data as JSON
The Aria Operations Management Pack builder can point at an online JSON or XML API and return fields for use in our custom management pack. I had considered enabling a web server (like IIS) to serve up a dynamic page read the energylog
and re-format the file as a JSON. This seemed like a bit of overkill, setting up IIS to server a single page. I then remembered seeing some code once to have powershell listen for http requests. I did a bit of searching and put the below code sample together. It listens for HTTP requests, then when one is received, powershell looks for the latest energylog
file, finds the last row with the newest data, then returns that data as a JSON object.
$httpListener = New-Object System.Net.HttpListener
$httpListener.Prefixes.Add('http://*:6545/')
$httpListener.Start()
while($true) {
$context = $httpListener.GetContext()
$context.Request.HttpMethod
$context.Request.Url
$context.Request.Headers.ToString() # pretty printing with .ToString()
# use a StreamReader to read the HTTP body as a string
$requestBodyReader = New-Object System.IO.StreamReader $context.Request.InputStream
$requestBodyReader.ReadToEnd()
Get-ChildItem 'C:\Program Files\APC\PowerChute Serial Shutdown\agent\energylog\*.log' | ?{$_.LastWriteTime -gt (Get-Date).AddMinutes(-10)} | Sort-Object LastWriteTime | Select-Object -first 1 | Foreach-Object {
# once we know the latest file, lets read the last line and split on the delimiter so we can assign the various parts to descriptive variables
$contentParts = (Get-Content $_.FullName -Tail 1).Split(';')
$responseJson = [pscustomobject][ordered]@{
'HostName' = $env:computername
'ModelName' = (Get-Content $_.FullName -TotalCount 10 |?{$_ -match 'modelname'}).Split('=')[1]
'FormattedDate' = (Get-Date).ToString('yyyy-MM-dd HH:mm')
'2010Date' = [int]$contentParts[0]
'relativeLoadPercentage' = [int]$contentParts[2]
'calculatedLoadWatts' = [float]$contentParts[3]
} | ConvertTo-Json
} # end file loop
$context.Response.StatusCode = 200
$context.Response.ContentType = 'application/json'
$responseBytes = [System.Text.Encoding]::UTF8.GetBytes($responseJson)
$context.Response.OutputStream.Write($responseBytes, 0, $responseBytes.Length)
$context.Response.Close() # end the response
} # end while loop
There is likely some room for improvement in that code, but as a proof of concept it seems to get the job done. I needed to open a Windows firewall port to allow incoming TCP 6545 requests, but we can test our ‘API’ from a remote machine easy enough, again using PowerShell:
Invoke-RestMethod -Uri 'http://servername.example.com:6545'
This should return the JSON object we created above. I created a scheduled task to start the above script when the system starts so that it is always running.
Management Pack Builder
For this part of the process, we’ll download the latest version of the Management Pack Builder appliance from https://marketplace.cloud.vmware.com/services/details/draft-vmware-aria-operation-management-pack-builder-1-1?slug=true and deploy it into our environment.
Our ‘API’ is super simple. Any request to the IP:Port will result in our JSON being returned. When building the management pack, we really don’t need much with authentication, special headers/request query strings, or object relationships. In fact, there are only three tabs where we need to fill in some details in Management Pack Builder, listed below.
Source
- Hostname: the name of our test system with the USB connected UPS & script running.
- Port: 6545
- SSL Configuration: No SSL
- Authentication: Custom, no details required since our ‘service’ doesn’t have authentication.
- Global Request Settings (optional): no configuration required.
- Test Connection Request: default GET, no configuration required.
- Test Connection Request Advanced: no configuration required.
- Test: Submit ‘Request’ button — should return the JSON object from script
Requests
I set the path to getStats
just to have something listed. Since our API is very simple we don’t require specific paths or headers. By default the request name will have the same value. Using the test ‘Request’ button should again return our expected JSON payload. We can then save our requests.
Objects
Next we’ll create an object using the ‘Add New Object’ button.
- Object Type: APC BackUPS
- Change Object Icon: Pick an icon, there is one that sort of looks like a battery, I piecked that one.
- Attributes from the API Request > expand ‘getStats’ > select all the attributes returned (except 2010date, I didn’t need that one)
- I left the hostname, model name, formatted date as string properties and the Relative Load Percentage and Calculated Load Watts as decimal metrics.
- Select object instance name: ‘Model Name’
- Select object identifiers: ‘Model Name’ + ‘Host Name’
Thats it! We now have enough of the management pack builder fields populated to build our PAK file. From the build tab we select ‘perform collection’ then ‘build’ and use the Pack File download link to get our file which should be about 20MB.
Installing and Configuring our Management Pack in Aria Operations
From there we can install our PAK file in Aria Operations. Instead of setting up the ‘VMware Aria Operations Connections’ feature inside of the Managment Pack Builder, I just switched over to Operations and selected Administration > Integrations > Repository > Add and browsed to my recently downloaded PAK file.
After our integration is installed, we should see an ‘Add Account’ button. Selecting the link will take us to the ‘Add Cloud Account’ page where we can enter the name & hostname of our connection. Here I’ve entered “Server Room UPS” for the name and “dr-control-21.lab.enterpriseadmins.org” as the hostname. Since no username/password are required for our ‘API’, these will be the only required fields.
After a few minutes, we should start seeing data flow into the metrics of our object. I took this screenshot after a few weeks of collection. We can check this out on the Metrics tab of the object and watch our calculated load over time as shown below:
Conclusion
Just because a device doesn’t provide an API doesn’t mean we can’t make our own. Using a bit of custom code + Management Pack Builder allows us to report on almost anything.