vSphere Reports in Microsoft Teams.

By joining PowerCLI to interrogate a VMware vSphere environment and the Webhook API to post Microsoft Teams messages, we can send informational reports on the state of a virtual environment to channels in Teams.

In this example I have a weekly report on the number of hosts and VMs in an environment. This is fairly straightforward, but more complicated information surfaced by PowerCLI could easily be included.

The resulting message in Teams

Setting up the WebHook

The Webhook allows messages to be pulled into the Teams channel of choice. You’ll need to setup an Incoming Webhook on your channel of choice.

To do this

  1. Right-click on the Teams Channel and choose Connectors
  2. Find Webhook in the list and click on the adjacent Configure button.
    Configure Webhook
  3. Enter a name, and choose an icon for the Webhook as prompted. Click on Create and a URL will be generated- this is needed for the script below.

Storing vCenter credentials

As this will be run as a scheduled task we need to store credentials so that the script doesn’t try to prompt for a password. There’s a number of ways of doing this- here I’ve used the Get-Credential cmdlet to prompt for the username and password and then the Export-CliXml cmdlet to save those credentials to a file.

1$Credential = Get-Credential
2$Credential | Export-CliXml -Path C:\Users\myuser\readonlyuser.cred

For the vCenter operations in the script below (counting hosts and VMs) then a user account with Read-Only access is sufficient.

The Script

Finally the script. This can be run manually or set as a scheduled task. The URL of the webhook created above needs to be entered as the value of the $TeamsWebhookURI variable at the top, along with the vCenter credentials and the name of the vCenter.

 1#Set the Webhook URI to send the message to
 3#Use pre-defined credentials
 4$credential = import-clixml -Path C:\Users\myuser\readonlyuser.cred
 5#What is the address of the vCenter?
 7#Connect to vCenter
 8Connect-VIServer -Server $vCenter -Credential $credential
 9  #Count the VMs and hosts
10  $poweredoff = @(get-vm | Where-object{$_.PowerState -ne "PoweredOn" } | measure-Object -Line).Lines
11  $poweredon = @(get-vm | Where-object{$_.PowerState -eq "PoweredOn" } | measure-Object -Line).Lines
12  $hostCount=(Get-VMHost | Measure-Object).Count
13#Disconnect from vCenter
14Disconnect-viserver -Server $vCenter -Confirm:$false
16#Build the JSON for the Body of the message
17$JSONBody = [PSCustomObject][Ordered]@{
18        "@type"      = "MessageCard"
19        "@context"   = "http://schema.org/extensions"
20        "summary"    = "Weekly Infrastructure Stats"
21        "themeColor" = '0078D7'
22        "sections"   = @(
23           @{
24       "activityTitle"    = "Virtual Infrastructure"
25              "activitySubtitle" = "Statistics"
26       "activityImage"    = "https://mydomain.com/infoicon.svg"
27              "facts"            = @(
28       @{
29       "name"  = "Num. of Hosts: "
30       "value" = $hostcount
31       },
32       @{
33       "name"  = "Powered On VMs: "
34       "value" = $poweredon
35       },
36       @{
37       "name"  = "Powered Off VMs: "
38       "value" = $poweredoff
39       },
40       @{
41       "name"  = "Total VMs: "
42       "value" =  ($poweredon+$poweredoff)
43       }
44       )
45       "markdown" = $true
46       }
48        )
49      }
50    $TeamMessageBody = ConvertTo-Json $JSONBody -Depth 100
52#Build the API call
53$parameters = @{
54        "URI"         = $TeamsWebhookURI
55        "Method"      = 'POST'
56        "Body"        = $TeamMessageBody
57        "ContentType" = 'application/json'
58    }
59#Make the API Call
60Invoke-RestMethod @parameters