{"id":2070,"date":"2024-11-14T16:24:53","date_gmt":"2024-11-14T21:24:53","guid":{"rendered":"https:\/\/enterpriseadmins.org\/blog\/?p=2070"},"modified":"2024-11-15T11:07:53","modified_gmt":"2024-11-15T16:07:53","slug":"leveraging-vmware-aria-operations-for-power-consumption-tracking","status":"publish","type":"post","link":"https:\/\/enterpriseadmins.org\/blog\/scripting\/leveraging-vmware-aria-operations-for-power-consumption-tracking\/","title":{"rendered":"Leveraging VMware Aria Operations for Power Consumption Tracking"},"content":{"rendered":"\n<p>I&#8217;ve been looking for a good reason to try out the Aria Operations Management Pack Builder, ever since a peer of mine <a href=\"https:\/\/enterpriseadmins.org\/blog\/virtualization\/learn-how-to-monitor-pi-hole-with-vrops-using-the-management-pack-builder\/\">built one for Pi-Hole<\/a> 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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Getting the data<\/h2>\n\n\n\n<p>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&#8217;t have a physical Windows system running 24&#215;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&#8217;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:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/enterpriseadmins.org\/blog\/wp-content\/uploads\/2024\/10\/image-1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"822\" height=\"98\" src=\"https:\/\/enterpriseadmins.org\/blog\/wp-content\/uploads\/2024\/10\/image-1.png\" alt=\"\" class=\"wp-image-2082\" srcset=\"https:\/\/enterpriseadmins.org\/blog\/wp-content\/uploads\/2024\/10\/image-1.png 822w, https:\/\/enterpriseadmins.org\/blog\/wp-content\/uploads\/2024\/10\/image-1-300x36.png 300w, https:\/\/enterpriseadmins.org\/blog\/wp-content\/uploads\/2024\/10\/image-1-768x92.png 768w\" sizes=\"auto, (max-width: 822px) 100vw, 822px\" \/><\/a><\/figure>\n\n\n\n<p>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 &gt; data log configuration, where you can set how frequently the service should record data.  I&#8217;ve set this to 5 minutes.  With this configuration enabled, there is a text file that is updated in this folder: <code>C:\\Program Files\\APC\\PowerChute Serial Shutdown\\agent\\energylog<\/code> 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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Formatting the data as JSON<\/h2>\n\n\n\n<p>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 <code>energylog<\/code> 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 <code>energylog<\/code> file, finds the last row with the newest data, then returns that data as a JSON object.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$httpListener = New-Object System.Net.HttpListener\n$httpListener.Prefixes.Add('http:\/\/*:6545\/')\n$httpListener.Start()\n\nwhile($true) {\n    $context = $httpListener.GetContext()\n    $context.Request.HttpMethod\n    $context.Request.Url\n    $context.Request.Headers.ToString() # pretty printing with .ToString()\n\n    # use a StreamReader to read the HTTP body as a string\n    $requestBodyReader = New-Object System.IO.StreamReader $context.Request.InputStream\n    $requestBodyReader.ReadToEnd()\n\n    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 {\n\n        # 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\n        $contentParts = (Get-Content $_.FullName -Tail 1).Split(';')\n        $responseJson = &#91;pscustomobject]&#91;ordered]@{\n            'HostName'               = $env:computername\n            'ModelName'              = (Get-Content $_.FullName -TotalCount 10 |?{$_ -match 'modelname'}).Split('=')&#91;1]\n            'FormattedDate'          = (Get-Date).ToString('yyyy-MM-dd HH:mm')\n            '2010Date'               = &#91;int]$contentParts&#91;0]\n            'relativeLoadPercentage' = &#91;int]$contentParts&#91;2]\n            'calculatedLoadWatts'    = &#91;float]$contentParts&#91;3]\n        } | ConvertTo-Json\n    } # end file loop\n\n    $context.Response.StatusCode = 200\n    $context.Response.ContentType = 'application\/json'\n\n    $responseBytes = &#91;System.Text.Encoding]::UTF8.GetBytes($responseJson)\n    $context.Response.OutputStream.Write($responseBytes, 0, $responseBytes.Length)\n\n    $context.Response.Close() # end the response\n} # end while loop<\/code><\/pre>\n\n\n\n<p>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 &#8216;API&#8217; from a remote machine easy enough, again using PowerShell:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Invoke-RestMethod -Uri 'http:\/\/servername.example.com:6545'<\/code><\/pre>\n\n\n\n<p>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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Management Pack Builder<\/h2>\n\n\n\n<p>For this part of the process, we&#8217;ll download the latest version of the Management Pack Builder appliance from <a href=\"https:\/\/marketplace.cloud.vmware.com\/services\/details\/draft-vmware-aria-operation-management-pack-builder-1-1?slug=true\">https:\/\/marketplace.cloud.vmware.com\/services\/details\/draft-vmware-aria-operation-management-pack-builder-1-1?slug=true<\/a> and deploy it into our environment.  <\/p>\n\n\n\n<p>Our &#8216;API&#8217; is super simple.  Any request to the IP:Port will result in our JSON being returned.  When building the management pack, we really don&#8217;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.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Source<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Hostname: the name of our test system with the USB connected UPS &amp; script running.  <\/li>\n\n\n\n<li>Port: 6545<\/li>\n\n\n\n<li>SSL Configuration: No SSL<\/li>\n\n\n\n<li>Authentication: Custom, no details required since our &#8216;service&#8217; doesn&#8217;t have authentication.<\/li>\n\n\n\n<li>Global Request Settings (optional): no configuration required.<\/li>\n\n\n\n<li>Test Connection Request: default GET, no configuration required.<\/li>\n\n\n\n<li>Test Connection Request Advanced: no configuration required.<\/li>\n\n\n\n<li>Test: Submit &#8216;Request&#8217; button &#8212; should return the JSON object from script<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Requests<\/h3>\n\n\n\n<p>I set the path to <code>getStats<\/code> just to have something listed.  Since our API is very simple we don&#8217;t require specific paths or headers.  By default the request name will have the same value. Using the test &#8216;Request&#8217; button should again return our expected JSON payload. We can then save our requests.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Objects<\/h3>\n\n\n\n<p>Next we&#8217;ll create an object using the &#8216;Add New Object&#8217; button. <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Object Type: APC BackUPS<\/li>\n\n\n\n<li>Change Object Icon: Pick an icon, there is one that sort of looks like a battery, I piecked that one.<\/li>\n\n\n\n<li>Attributes from the API Request &gt; expand &#8216;getStats&#8217; &gt; select all the attributes returned (except 2010date, I didn&#8217;t need that one)<\/li>\n\n\n\n<li>I left the hostname, model name, formatted date as string properties and the Relative Load Percentage and Calculated Load Watts as decimal metrics.<\/li>\n\n\n\n<li>Select object instance name: &#8216;Model Name&#8217;<\/li>\n\n\n\n<li>Select object identifiers: &#8216;Model Name&#8217; + &#8216;Host Name&#8217;<\/li>\n<\/ul>\n\n\n\n<p>Thats it!  We now have enough of the management pack builder fields populated to build our PAK file.  From the build tab we select &#8216;perform collection&#8217; then &#8216;build&#8217; and use the Pack File download link to get our file which should be about 20MB.  <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Installing and Configuring our Management Pack in Aria Operations<\/h2>\n\n\n\n<p>From there we can install our PAK file in Aria Operations. Instead of setting up the &#8216;VMware Aria Operations Connections&#8217; feature inside of the Managment Pack Builder, I just switched over to Operations and selected Administration &gt; Integrations &gt; Repository &gt; Add and browsed to my recently downloaded PAK file.<\/p>\n\n\n\n<p>After our integration is installed, we should see an &#8216;Add Account&#8217; button. Selecting the link will take us to the &#8216;Add Cloud Account&#8217; page where we can enter the name &amp; hostname of our connection. Here I&#8217;ve entered &#8220;Server Room UPS&#8221; for the name and &#8220;dr-control-21.lab.enterpriseadmins.org&#8221; as the hostname. Since no username\/password are required for our &#8216;API&#8217;, these will be the only required fields.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/enterpriseadmins.org\/blog\/wp-content\/uploads\/2024\/11\/image.png\"><img loading=\"lazy\" decoding=\"async\" width=\"722\" height=\"382\" src=\"https:\/\/enterpriseadmins.org\/blog\/wp-content\/uploads\/2024\/11\/image.png\" alt=\"\" class=\"wp-image-2112\" srcset=\"https:\/\/enterpriseadmins.org\/blog\/wp-content\/uploads\/2024\/11\/image.png 722w, https:\/\/enterpriseadmins.org\/blog\/wp-content\/uploads\/2024\/11\/image-300x159.png 300w\" sizes=\"auto, (max-width: 722px) 100vw, 722px\" \/><\/a><\/figure>\n\n\n\n<p>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:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/enterpriseadmins.org\/blog\/wp-content\/uploads\/2024\/11\/image-1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"942\" height=\"662\" src=\"https:\/\/enterpriseadmins.org\/blog\/wp-content\/uploads\/2024\/11\/image-1.png\" alt=\"\" class=\"wp-image-2113\" srcset=\"https:\/\/enterpriseadmins.org\/blog\/wp-content\/uploads\/2024\/11\/image-1.png 942w, https:\/\/enterpriseadmins.org\/blog\/wp-content\/uploads\/2024\/11\/image-1-300x211.png 300w, https:\/\/enterpriseadmins.org\/blog\/wp-content\/uploads\/2024\/11\/image-1-768x540.png 768w\" sizes=\"auto, (max-width: 942px) 100vw, 942px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>Just because a device doesn&#8217;t provide an API doesn&#8217;t mean we can&#8217;t make our own.  Using a bit of custom code + Management Pack Builder allows us to report on almost anything.  <\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;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 &hellip; <a href=\"https:\/\/enterpriseadmins.org\/blog\/scripting\/leveraging-vmware-aria-operations-for-power-consumption-tracking\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":6,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[9,3],"tags":[],"class_list":["post-2070","post","type-post","status-publish","format-standard","hentry","category-lab-infrastructure","category-scripting"],"_links":{"self":[{"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/posts\/2070","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/comments?post=2070"}],"version-history":[{"count":11,"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/posts\/2070\/revisions"}],"predecessor-version":[{"id":2125,"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/posts\/2070\/revisions\/2125"}],"wp:attachment":[{"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/media?parent=2070"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/categories?post=2070"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/tags?post=2070"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}