Getting familiar with the local REST API in VMware Workstation. First up, start vmrest and use its browser interface to see which operations are available. Then we can turn those same requests into PowerShell.

The current API reference lives under Broadcom’s developer docs:

VMware Workstation Pro API

Configure vmrest credentials

From the VMware Workstation installation directory, configure credentials for the REST API:

cd "C:\Program Files (x86)\VMware\VMware Workstation"
.\vmrest.exe -C

Example output:

VMware Workstation REST API
Copyright (C) 2018-2019 VMware Inc.
All Rights Reserved

vmrest 1.2.0 build-14665864

Username:chadduffey

New password:
Retype new password:

Processing...
Credential updated successfully

Then start the service:

.\vmrest.exe

By default it serves the API locally:

Serving HTTP on 127.0.0.1:8697

That local binding is a good thing. This service controls local virtual machines, so do not casually expose it to the network.

Use the API explorer

Open the local vmrest URL in a browser to view the API explorer. The explorer is useful because it shows the available endpoints and lets you test requests interactively.

Use the Authorize button and provide the username and password you configured with -C. The sample requests will then include the required Authorization header.

The API uses Basic authentication. If you are scripting against the default local HTTP endpoint, remember that the risk model assumes local access. If you change binding or routing in future versions, treat that credential like any other administrative credential.

Calling it from PowerShell

Create the Basic auth header:

$credential = Get-Credential -UserName 'chadduffey' -Message 'vmrest credentials'
$basic = [Convert]::ToBase64String(
    [Text.Encoding]::ASCII.GetBytes(
        '{0}:{1}' -f $credential.UserName, $credential.GetNetworkCredential().Password
    )
)

$headers = @{
    Accept = "application/vnd.vmware.vmw.rest-v1+json"
    Authorization = "Basic $basic"
}

List registered VMs:

Invoke-RestMethod -Uri "http://127.0.0.1:8697/api/vms" -Headers $headers

Example output:

id                               path
--                               ----
F7G7IGFGK9KDT7UD72J24EL9AN9NPPPF D:\Ubuntu-Dev\Ubuntu Dev.vmx
KR5VJF8603O2NP18J8TNIGN0V8TKNOH9 D:\Win2k3-2\Win2k3-2.vmx
T5E8QNC0QPF842N8CAH8IPMF78VCNMDJ D:\client1\Client1.vmx

From there, you can use the returned VM IDs for follow-up operations.

A small lab helper

For lab work, the most useful automation is often “show me what is registered and let me power on a specific machine.”

$baseUri = "http://127.0.0.1:8697/api"

$vms = Invoke-RestMethod -Uri "$baseUri/vms" -Headers $headers
$vms | Format-Table id, path

$matchingVms = @($vms | Where-Object { $_.path -eq 'D:\client1\Client1.vmx' })

if ($matchingVms.Count -ne 1) {
    throw "Expected exactly one VM at the requested path; found $($matchingVms.Count)"
}
$target = $matchingVms[0]

Invoke-RestMethod `
    -Uri "$baseUri/vms/$($target.id)/power" `
    -Method Put `
    -Headers $headers `
    -Body 'on' `
    -ContentType "application/vnd.vmware.vmw.rest-v1+json"

Replace the path with one from your VM list. The power endpoint takes an operation such as on or shutdown; the power_state object is its response, not the request body. Use the local API explorer’s generated request to check the format against your installed version.

Read the state back with:

Invoke-RestMethod -Uri "$baseUri/vms/$($target.id)/power" -Headers $headers

poweredOn tells us the virtual machine is running. It doesn’t mean Windows has booted, AD is ready or the service inside it is accepting connections. A lab startup script needs to check the thing its next step depends on.

The functionality felt a little sad when I first went looking for a full lab-provisioning API. But listing machines and controlling power is enough to remove a fair bit of clicking. vmrun is worth looking at for operations the REST API doesn’t expose.

References