Category Archives: How To….

Using PowerShell and REST-API to create a VM in vCenter

VMware vSphere 6.5 comes with a RESTful API implementation and there’s some great documentation out there- starting with the API Explorer ( ). Here’s a quick piece on how to use this API to create a VM from the PowerShell command line. This is intentionally not using PowerCLI,  just the native PowerShell cmdlets- partly as a REST learning experience for me, and partly so the API code can be transferred to another language at a later date.

Step 1- Authenticate with the Server.

This step is well documented by Chris Wahl. I’ve borrowed some of his code here, and accompanied it with a section to get around the lack of trusted certificates on my homelab. is the IP of my VCSA, so if you’re reusing this anywhere remember to replace that hard coded value where it appears.

#Step 1- Authenticate with the Server
#Ignore Server Certs- This is on my not-very-well-certified home lab.
if (-not ([System.Management.Automation.PSTypeName]'ServerCertificateValidationCallback').Type)
using System;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
public class ServerCertificateValidationCallback
public static void Ignore()
if(ServicePointManager.ServerCertificateValidationCallback ==null)
ServicePointManager.ServerCertificateValidationCallback +=
Object obj,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors errors
return true;
Add-Type $certCallback

#Get Some Credentials and Determine Authorisation Methods
$Credential = Get-Credential
$auth = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Credential.UserName+':'+$Credential.GetNetworkCredential().Password))
$head = @{
'Authorization' = "Basic $auth"

#Authenticate against vCenter
$r = Invoke-WebRequest -Uri -Method Post -Headers $head
$token = (ConvertFrom-Json $r.Content).value
$session = @{'vmware-api-session-id' = $token}

Now we have the Session ($session) we can test this by retrieving a list of VMs.

#Get a List of VMs
$r1 = Invoke-WebRequest -Uri -Method Get -Headers $session
$vms = (ConvertFrom-Json $r1.Content).value

Step 2- Construct the JSON specification

To create a new VM we need to provide a minimal spec for the machine, in JSON format. We need to tell it the intended Guest OS, what datastore is going to hold the VM, and where the VM will be placed in the resource/folder structure. To complete this we need to establish what options are available- just sticking in the display names of a datastore or folder from the Web Client will not work and will likely generate 404 responses to the API call.

To find these names we can use the API, API explorer gives us the following urls

Datastore:       /rest/vcenter/datastore
Folder:              /rest/vcenter/folder
Resource Pool: /rest/vcenter/resource-pool

So we can use PowerShell to retrieve a list of Datastores using this line of code

(Invoke-RestMethod -Uri -Method Get -Headers $session ).value

which will produce a list of datastores, each looking something like this:

datastore  : datastore-11
name       : Datastore2
type       : VMFS
free_space : 100553195520
capacity   : 249913409536

From this example we want the value of the “datastore” field, e.g “datastore-11”.

Once we have this information we can combine it all to create a JSON spec file. My example looks like this:

"spec": {
"guest_OS": "RHEL_7_64",
"placement" : {
"datastore": "datastore-11",
"folder": "group-v224",
"resource_pool": "resgroup-182"

Step 3- Create the Virtual Machine.

Now we’ve done all this prep work, creating a Virtual Machine comes down to a single line of PowerShell pointing at the data.txt file containing the JSON code from Step 2.

Invoke-WebRequest -Uri -Method Post -Headers $session -ContentType "application/json" -Body (Get-Content data.txt)

Example Output:

StatusCode        : 200
StatusDescription : OK
Content           : {"value":"vm-462"}
RawContent        : HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json
Date: Mon, 27 Mar 2017 09:41:34 GMT

Forms             : {}
Headers           : {[Transfer-Encoding, chunked], [Content-Type, application/json], [Date, Mon, 27 Mar 2017 09:41:34 GMT]}
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        : mshtml.HTMLDocumentClass
RawContentLength  : 18

The VM is created and we can check this from the vSphere Client:

2017-03-27 (10)

So, to summarise. Native PowerShell, with a little bit of JSON, can be used to communicate with the vSphere APIs and create new Virtual Machines. Depending on your use case there may be better ways of implementing automation processes through this API (PowerCLI is a good start) but if you want to drop to the raw RESTful API, possibly as a stepping stone to a larger project, PowerShell provides a handy method to get started down that path.

PowerShell Quick Tip- Letter Frequency

With a list of Surnames in a text file I wanted to see how many start with A, how many with B, and so on. This is my PowerShell solution:

(Get-Content .\surnames.txt).Substring(0,1).ToUpper() |
  Sort-Object | Group-Object |Select-Object Name, Count

Example Input (surnames.txt file):


Example Output:

Name Count
---- -----
A      162
B      372
C      365
D      193
E      187
F      198
G      154
H      321

Mailbox filling up harddisk? Turn Off Cached Exchange Mode

Microsoft OutlookThis came up in conversation at work earlier today- a user has connected to their own mailbox and those of other staff. They now have a whopping 35GB of Outlook files on their workstation. They are having performance issues. Here’s a 30-second highlight of the solution.

Solution: Turn off Cached Exchange Mode in Outlook, reduce the timespan mail is retained locally, or choose not to cache the shared mailboxes.

What is Cached Exchange Mode?
Cached Exchange Mode is used in Outlook to download a local copy of a mailbox on the workstation to allow for offline use. This is the default behaviour when connecting to Exchange and is great for most users, and in particular if you have a poor or intermittent network connection. However when used by people using massive mailboxes it can take up a lot of local hard drive space- you’ll spot some large “.OST” files in the users profile-  and Microsoft advise that performance can become an issue on large (>25GB) mailboxes.

My (default) settings on a workstation look like the screenshot below- Cached Exchange Mode is turned on and set to download the last 12 months of data from all mailboxes I connect to with that account and also the GAL. If I look in C:\Users\username\AppData\Local\Microsoft\Outlook I see that I have an OST file weighing in just under 1.5GB however my mailbox on the Exchange Server (Office365) is 10GB in size. With these settings I can access all the mail I need to, and if I need to look up anything earlier it goes off to the server to retrieve it- this process is barely noticable if I’m connected to the internet.

If I need to reclaim some local disk space, or hit performance issues, I can reduce this local retention time or disable Cached Exchange Mode altogether.

Cached Exchange Mode Settings

ESXi UNMAP not working on Replicated EqualLogic Volume


  • The VMware vSphere ESXi UNMAP command doesn’t release space on some or all volumes on a Dell EqualLogic SAN array running v8 firmware (may apply to other versions too). Using the following command in an SSH session to a 6.0u2 host (again, will apply to other versions):
    esxcli storage vmfs unmap –l MYVOLUMENAME
  • The volumes are VMFS5 (and always have been- they haven’t been upgraded from VMFS3).
  • Replication is enabled for the volumes that won’t rethin.



UNMAP doesn’t work on the EqualLogic when Replication is enabled. It doesn’t return an error to the SSH session, and the temporary rethinning file is still created, but the disk is not thinned.


Disable replication on the volume, re-thin the volume using the UNMAP command, then re-configure replication. Unfortunately this means the entire volume must be re-copied to the replication partner and this may impact bandwidth usage and replication schedules on larger volumes.


Finding Deprecated VMFS Volumes

Following an upgrade to vSphere 6, hosts popped up an error message reporting that some old VMFS volumes were found on the host. Whilst these still worked, it would be prudent to tidy them up and replace them with modern datastores. The message is:

“Deprecated VMFS volume(s) found on the host. Please consider upgrading volume(s) to the latest version”


Whilst this highlights that there is an issue, the GUI message doesn’t indicate which volumes (or how many) are affected. The following quick bit of PowerCLI produces a table of the datastores with a VMFS version of less than 5.

Get-Datastore |
 Where-Object { $_.ExtensionData.Info.VMFS.MajorVersion -lt 5} |
 Select-Object Name, FreeSpaceGB, CapacityGB, @{n='VMFS Version';e={$_.ExtensionData.Info.VMFS.MajorVersion}}

Example Output:

Name           FreeSpaceGB CapacityGB VMFS Version
----           ----------- ---------- ------------
VOL-VM01            574.77    2047.75            3
VOL-VM02           1924.05    2047.75            3