To automate virtualization the primary API from VMware is VIX. This api is released for both VMware Fusion, VMware Workstation Pro, and VMware Player. But it is not included in all products. Then you have to download and install the API manually.

The VIX API documentation is available on the VMware support (link). Here there is also a reference to the tool vmrun. Maybe I will get back to this later...

Unfortunately the API is not really maintained anylonger. The last version (1.17) is from 2017-09-26. This is too long ago. Especially when you look at all the nice things you can do on Hyper-V with PowerShell CmdLets (link).
One answer could be the new REST API, but that is too limited to be usefull. I have taken a breif look at this API earlier (link).
Another API from VMware is PowerCLI, which is actually a PowerShell interface. But this API does not work with VMware Workstation. That is a really bad decision from VMware.
Not that PowerCLI is fantastic. I think that they got the basics on PowerShell somewhat wrong.
At the PowerShell Galley VMware has the module VMware.VimAutomation.Core (link). But like PowerCLI this module is only for vSphere and can then not be used with VMware Workstation.

With VMware Workstation Pro VIX is installed in the path “%ProgramFiles(x86)%\VMware\VMware VIX\„. In this folder there are three folders with documentation (doc), examples (samples) and implementations for VMware Workstation 15 (Workstation-15.0.0). The implementation on WMware Workstation is both 32- and 64-bit.
Please notice that the documentation in the local doc folder is not complete. You should use the online documentation (link).
Also the folder holds C++ code files. Actually VIX is a C++ SDK with a COM implementation. They are in the VIX folder and the Workstation subfolder.


There is a wrapper for the VIX COM interface on GitHub in the project VMWareTasks. The wrapper is written in and for C#. The code is 32-bit only, which might give some issues on a modern 64-bit platform.
But unfortunately this project has not been updated since 2015-11-30. This is more than a year before the last update to VIX. In my point of view this project looks somewhat cold.


I can add a type in PowerShell on a VIX DLL file like
Add-Type -LiteralPath $VixFile.FullName -PassThru
But even I use the PassThru option the is neither error or type info.
After I have added a type and try to address is with
$Vix = New-Object -ComObject 'Vix.COM'
things go wrong deep inside .NET with the error "Bad IL format".

Still I have not been able to figure out how to connect PowerShell to VIX using COM.

There are a lot of Perl examples, but using Perl integrates bad with my general infrastructure automation, which is based on PowerShell.


PowerShell function switch parameter

I played a little with switch parameters to a PowerShell function. The initial purpose was to see how to use default values on switch parameters.
A quick (and dirty) function to test various usages of a switch parameter:

function Test-Switch {
    param (
        [switch]$SwitchTwo = $false
    if($SwitchOne) { 'One is True' }
    else { 'One is False' }

    if($SwitchTwo) { 'Two is True' }
    else { 'Two is False' }

I call the function in different ways like this:

'--- (true) (none) ---'
Test-Switch -SwitchOne
'--- false (none) ---'
Test-Switch -SwitchOne:$false
'--- (true) (false) ---'
Test-Switch -SwitchOne -SwitchTwo
'--- false true ---'
Test-Switch -SwitchOne:$false -SwitchTwo:$true
'--- (true) false ---'
Test-Switch -SwitchOne -SwitchTwo:$false

And the output is:

--- (true) (none) ---
One is True
Two is False
--- false (none) ---
One is False
Two is False
--- (true) (false) ---
One is True
Two is True
--- false true ---
One is False
Two is True
--- (true) false ---
One is True
Two is False

When I take a step back the functionality with a binary switch parameter to a PowerShell function is a nice feature.
But it should be used with caution.
Remember the principle to check for positives. So a usage of a false default I would consider more than twice.


VMware Workstation REST API

With VMware Workstation Pro there is a REST API where you can manage virtual machines. This API has a standard protocol that can be handled by the PowerShell CmdLet Invoke-RestMethod.
I have looked into this with PowerShell Core 6 and it basically works fine.

To set up the REST API on your local VMware Workstation Pro there is a fine guide on this by VMware: "Use the VMware Workstation Pro REST API Service". You should notice that you have to initialize the API before use. and that the REST API is only active while you have running by the command-tool vmrest.exe.

There are several independant writings on the VMware REST API, but most are in relation to vCenter where you are working on a remote connection and the security is tighter. When you are working on a local VMWare Workstation you can omit most encryption and work on http direct.

After initializing the REST API there are some PowerShell workarounds to get the credential to work. This is described in detail by others like in the blog entry "Introduction to PowerShell REST API authentication". Most are against vCenter but works on a local VMware Workstation. In my case this works fine:

  $Credential = Get-Credential
  $Auth = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Credential.UserName + ':' + $Credential.GetNetworkCredential().Password))
  $head = @{
    'Authorization' = "Basic $Auth"

  $RestApiServer = ''
  $BaseUri = "http://$RestApiServer"

To get a list of defined virtual machines one call is enough:

  $vmListUri = $BaseUri + '/api/vms'
  "URI = $vmListUri" | Write-Debug
  $vmList = Invoke-RestMethod -Method Get -Uri $vmListUri -Headers $head

Unfortunately it looks like the REST API is rather limited in functionality. By calling the REST API in a web browser it presents the funtionality on virtual macine management like this:

I can create a copy of a existing virtual machine, but not create a new from scratch. This is just one example of features that I miss.

Mayby I should take another look at the VMware VIX API, even it is based on elder technology that fits poorly with PowerShell Core.



AMD has launched the new generation of their server processor EPYC with the Zen 2 design. It looks really promising, and I look foreward to see some performance figures from the real world.

I will not go into the technical details om the processor, as there are others who already has done that. And far better than I will be able to:
  • ars technica: A detailed look at AMD’s new Epyc “Rome” 7nm server CPUs (link)
  • ServeTheHome: AMD EPYC 7002 Series Rome Delivers a Knockout (link)
  • AnadTech: AMD Rome Second Generation EPYC Review (link)
  • Storage Review: AMD EPYC Rome 7002 Series Launched (link)
  • tom's hardware: AMD Unveils 7nm EPYC Rome Processors (link)


Windows Storage Spaces

To look into Windows Storage Spaces on if and how to use it on a SQL Server database server I have added 5 SCSI disks to a virtual server running Windows Server 2016 on vmware Workstation.
Please notice that I am working with the local Windows Storage Spaces and not the networked Storage Spaces Direct (S2D). The physical disk on the host is a Samsung 970 Evo NVMe SSD also hosting the host OS Windows 10 Pro.

On these 5 disks I create a storage pool where I create 2 Virtual Disks of different size and with different allocation unit size. The allocation units are of different size with a SQL Server installation in mind.
Also the logical sector size in the storage pool is set to 4KB where the default is 512B. This is to see how easy it is to change this and maybe later experiment further with the impact of a larger logical sector size.

The storage pool is created with the CmdLet New-StoragePool:

New-StoragePool -FriendlyName Pool_00 -StorageSubSystemFriendlyName (Get-StorageSubSystem).FriendlyName -PhysicalDisks (Get-PhysicalDisk -CanPool $true) -LogicalSectorSizeDefault 4KB

The CmdLet return

FriendlyName OperationalStatus HealthStatus IsPrimordial IsReadOnly
------------ ----------------- ------------ ------------ ----------
Pool_00      OK                Healthy      False        False   

Then the first Virtual Disk is created with the CmdLet New-VirtualDisk:

New-VirtualDisk -StoragePoolFriendlyName Pool_00 -FriendlyName ProgramDisk -ResiliencySettingName Mirror -NumberOfDataCopies 3 -Size (42GB) -ProvisioningType Thin

This CmdLet return

FriendlyName ResiliencySettingName OperationalStatus HealthStatus IsManualAttach  Size
------------ --------------------- ----------------- ------------ --------------  ----
ProgramDisk  Mirror                OK                Healthy      False          42 GB

To create a partition on the Virtual Disk and format the volume with ReFS a small PowerShell script does it:

Get-VirtualDisk -FriendlyName ProgramDisk | Get-Disk |
Initialize-Disk -PartitionStyle GPT -PassThru |
New-Partition -DriveLetter F -UseMaximumSize |
Format-Volume -NewFileSystemLabel Program -FileSystem ReFS

This small script return

DriveLetter FileSystemLabel FileSystem DriveType HealthStatus OperationalStatus SizeRemaining     Size
----------- --------------- ---------- --------- ------------ ----------------- -------------     ----
F           Program         ReFS       Fixed     Healthy      OK                     40.93 GB 41.81 GB

When the disk is created a dialog about formatting the drive might be shown like this

To check the volume I use the command-line tool fsutil:

.\fsutil.exe fsinfo refsinfo F:

The tool return

REFS Volume Serial Number :       0xee841e1a841de63d
REFS Version   :                  3.1
Number Sectors :                  0x0000000000a74000
Total Clusters :                  0x0000000000a74000
Free Clusters  :                  0x0000000000a3bb69
Total Reserved :                  0x0000000000018510
Bytes Per Sector  :               4096
Bytes Per Physical Sector :       4096
Bytes Per Cluster :               4096
Checksum Type:                    CHECKSUM_TYPE_NONE

The second Virtual Disk is created with

New-VirtualDisk -StoragePoolFriendlyName Pool_00 -FriendlyName DataDisk -ResiliencySettingName Mirror -NumberOfDataCopies 3 -Size (123GB) -ProvisioningType Thin

A return similar to last time

FriendlyName ResiliencySettingName OperationalStatus HealthStatus IsManualAttach   Size
------------ --------------------- ----------------- ------------ --------------   ----
DataDisk     Mirror                OK                Healthy      False          123 GB

The volume is created and formatted with the small script:

Get-VirtualDisk -FriendlyName DataDisk | Get-Disk |
Initialize-Disk -PartitionStyle GPT -PassThru |
New-Partition -DriveLetter H -UseMaximumSize |
Format-Volume -NewFileSystemLabel Data -FileSystem ReFS -AllocationUnitSize 64KB

And the return is

DriveLetter FileSystemLabel FileSystem DriveType HealthStatus OperationalStatus SizeRemaining      Size
----------- --------------- ---------- --------- ------------ ----------------- -------------      ----
H           Data            ReFS       Fixed     Healthy      OK                    121.77 GB 122.81 GB

Check the volume

.\fsutil.exe fsinfo refsinfo H:

The tool return

REFS Volume Serial Number :       0x2620bb5220bb27a7
REFS Version   :                  3.1
Number Sectors :                  0x0000000001eb4000
Total Clusters :                  0x00000000001eb400
Free Clusters  :                  0x00000000001e710d
Total Reserved :                  0x00000000000027c8
Bytes Per Sector  :               4096
Bytes Per Physical Sector :       4096
Bytes Per Cluster :               65536
Checksum Type:                    CHECKSUM_TYPE_NONE


This is just to look in the creation of a storage pool with different Virtual Disks in Windows Storage Spaces. Looking at performance and optimal configuration for SQL Server are other and later writings.

Please notice that Windows can't boot on a storage pool. This gives that you have to configure a more traditional storage for booting and running Windows. Here there is no difference between Windows Server and Windows desktop OS.

A quick thought though is that I think that I would avoid tiered storage. Just as in a SAN configuration for SQL Server.