Using PowerCLI SPBM cmdlets to create VMs with storage policy

Recently I was looking for a way to consume the Storage Policy Based Management (SPBM) cmdlets in PowerCLI. I wanted to see if I could provision a VM from a Template onto my vSAN datastore with a particular policy rather than simply change it after it was deployed. It wasn’t as easy as I thought, as some of the commands I tried would only change the VM Home Namespace to the new policy, and leave the disks with the default datastore policy. And when I tried to clone a new VM from a template, I couldn’t get the VM to pick up the policy at all. After much trial and error, and some guidance from one of our PowerCLI engineers, Manish Tiwari, we eventually managed to achieve what I set out to so. Here are some examples if you wish to do something like this yourself. Note this is PowerCLI version 10.1.0 build 8346946. The commands are run against a vSphere 6.7 GA deployment.

1. Use New-VM with Set-SpbmEntityConfiguration to set the policy

Result: Works on VM Home Namespace only.

PS C:\Users\chogan>New-VM -Name 30julytest3 -Datastore vsanDatastore \
-ResourcePool CH-Cluster | Set-SpbmEntityConfiguration -StoragePolicy RAID-5


Entity                 Storage Policy                 Status          Time Of Check
------                 --------------                 ------          -------------
30julytest3            RAID-5                         compliant       7/30/2018 9:38:12 AM


PS C:\Users\chogan>Get-VM -Name 30julytest3 | Get-SpbmEntityConfiguration

Entity                 Storage Policy                 Status          Time Of Check
------                 --------------                 ------          -------------
30julytest3            RAID-5                         compliant       7/30/2018 9:38:12 AM

PS C:\Users\chogan>Get-VM -Name 30julytest3 | Get-Harddisk | Get-SpbmEntityConfiguration

Entity                 Storage Policy                 Status          Time Of Check
------                 --------------                 ------          -------------
Hard disk 1            vSAN Default Storage Policy    compliant       7/30/2018 9:38:07 AM


2. Use New-VM with -AdvancedOption to set the policy

Result: Works for both VM Home Namespace and Hard Disks.

PS C:\Users\chogan>$policy = Get-SpbmStoragePolicy RAID-5
PS C:\Users\chogan>echo $policy

Name                 Description                           AnyOfRuleSets                  CommonRule
----                 -----------                           -------------                  ----------
RAID-5                                                     {(VSAN.hostFailuresToTolera... {}

PS C:\Users\chogan>New-VM -Name 30julytest1 -Datastore vsanDatastore \
-ResourcePool CH-Cluster -AdvancedOption $policy

Name                 PowerState Num CPUs MemoryGB
----                 ---------- -------- --------
30julytest1          PoweredOff 1        0.250

PS C:\Users\chogan> Get-VM -Name 30julytest1 | Get-SpbmEntityConfiguration

Entity                 Storage Policy                 Status          Time Of Check
------                 --------------                 ------          -------------
30julytest1            RAID-5                         compliant       7/30/2018 8:50:07 AM

PS C:\Users\chogan> Get-VM -Name 30julytest1 | Get-Harddisk | Get-SpbmEntityConfiguration

Entity                 Storage Policy                 Status          Time Of Check
------                 --------------                 ------          -------------
Hard disk 1            RAID-5                         compliant       7/30/2018 8:50:07 AM

3. Use New-VM (clone from template) with Set-SpbmEntityConfiguration to set the policy

Result: Works on VM Home Namespace only. Same as #1.

4. Use New-VM (clone from template) with -AdvancedOption to set the policy

Result: Doesn’t work at all. Both VM Home Namespace and Hard Disk get default policy, not requested policy.

PS C:\Users\chogan>$policy = Get-SpbmStoragePolicy RAID-5
PS C:\Users\chogan>echo $policy

Name                 Description                           AnyOfRuleSets                  CommonRule
----                 -----------                           -------------                  ----------
RAID-5                                                     {(VSAN.hostFailuresToTolera... {}

PS C:\Users\chogan> New-VM -Name 30julytest2 -Template win7-desktop-orig \
-Datastore vsanDatastore -ResourcePool CH-Cluster -AdvancedOption $policy

Name                 PowerState Num CPUs MemoryGB
----                 ---------- -------- --------
30julytest2          PoweredOff 1        2.000 PS 

PS C:\Users\chogan> Get-VM -Name 30julytest2 | Get-SpbmEntityConfiguration

Entity                 Storage Policy                 Status          Time Of Check 
------                 --------------                 ------          ------------- 
30julytest2            vSAN Default Storage Policy    compliant       7/30/2018 9:31:04 AM PS

PS C:\Users\chogan> Get-VM -Name 30julytest2 | Get-Harddisk | Get-SpbmEntityConfiguration 

Entity                 Storage Policy                 Status          Time Of Check 
------                 --------------                 ------          -------------
Hard disk 1            vSAN Default Storage Policy    compliant       7/30/2018 9:31:04 AM

5. Multi-command solution using New-VM (clone from template) with Set-SpbmEntityConfiguration to set the policy

Result: It works, but it is not ideal since the VM is first created with one policy and needs to be rebuilt with a new policy, which leads to resync traffic.

PS C:\Users\chogan> New-VM -Name 30julytest -Template win7-desktop-orig \ 
-Datastore vsanDatastore -ResourcePool CH-Cluster

Name                PowerState Num CPUs MemoryGB 
----                ---------- -------- -------- 
30julytest          PoweredOff 1        2.000 PS

PS C:\Users\chogan> Get-VM -Name 30julytest | Get-SpbmEntityConfiguration  

Entity                 Storage Policy                 Status          Time Of Check 
------                 --------------                 ------          ------------- 
30julytest             vSAN Default Storage Policy    compliant       7/30/2018 11:54:04 AM 

PS PS C:\Users\chogan> Get-VM -Name 30julytest | Get-Harddisk | \
Get-SpbmEntityConfiguration  

Entity                 Storage Policy                 Status          Time Of Check 
------                 --------------                 ------          ------------- 
Hard disk 1            vSAN Default Storage Policy    compliant       7/30/2018 11:54:12 AM


PS C:\Users\chogan> Get-VM -Name 30julytest  | Set-SpbmEntityConfiguration \
 -StoragePolicy RAID-5

Entity                 Storage Policy                 Status          Time Of Check
------                 --------------                 ------          -------------
30julytest             RAID-5                         compliant       7/30/2018 11:54:28 AM

PS C:\Users\chogan> Get-VM -Name 30julytest  | Get-Harddisk | \
Set-SpbmEntityConfiguration -StoragePolicy RAID-5

Entity                 Storage Policy                 Status          Time Of Check
------                 --------------                 ------          -------------
Hard disk 1            RAID-5                         compliant       7/30/2018 11:55:27 AM


PS C:\Users\chogan> Get-VM -Name 30julytest | Get-SpbmEntityConfiguration

Entity                 Storage Policy                 Status          Time Of Check
------                 --------------                 ------          -------------
30julytest             RAID-5                         compliant       7/30/2018 11:54:28 AM

 
PS C:\Users\chogan> Get-VM -Name 30julytest | Get-Harddisk | \
Get-SpbmEntityConfiguration

Entity                 Storage Policy                 Status          Time Of Check
------                 --------------                 ------          -------------
Hard disk 1            RAID-5                         compliant       7/30/2018 11:55:27 AM

6. Single command solution using New-VM with Set-SpbmEntityConfiguration to set the policy

Result: Sort of works. The following can be used so long as there is more than one disk attached to the VM. It doesn’t work when there is only a single disk.

PS C:\Users\chogan> New-VM -Name 30julytest6  -Datastore vsanDatastore \
-ResourcePool CH-Cluster -DiskGB 1,2 -AdvancedOption \
(Get-SpbmStoragePolicy RAID-5) | %{((Get-HardDisk -VM $_) + $_)} | \
Set-SpbmEntityConfiguration -StoragePolicy RAID-5

Entity                 Storage Policy                 Status          Time Of Check
------                 --------------                 ------          -------------
Hard disk 1            RAID-5                         compliant       7/30/2018 2:26:54 PM
Hard disk 2            RAID-5                         compliant       7/30/2018 2:26:59 PM
30julytest6            RAID-5                         compliant       7/30/2018 2:27:02 PM

7. Single command solution using New-VM (clone from template) with Set-SpbmEntityConfiguration to set the policy

Result: Same as #6 – sort of works. The following can be used so long as there is more than one disk attached to the VM. It doesn’t work when there is only a single disk.

PS C:\Users\chogan> New-VM -Name 30julytest5 -Template win7-desktop-orig -Datastore \
vsanDatastore -ResourcePool CH-Cluster  -OSCustomizationSpec win7 -AdvancedOption \
(Get-SpbmStoragePolicy RAID-5) | %{((Get-HardDisk -VM $_) + $_)} | \
Set-SpbmEntityConfiguration -StoragePolicy RAID-5

Entity                 Storage Policy                 Status          Time Of Check
------                 --------------                 ------          -------------
Hard disk 1            RAID-5                         compliant       7/30/2018 2:49:34 PM
Hard disk 2            RAID-5                         compliant       7/30/2018 2:49:39 PM
30julytest5            RAID-5                         compliant       7/30/2018 2:49:44 PM

8. Single command solution using New-VM (clone from template) with Set-SpbmEntityConfiguration to set the policy

Result: This will work when there are one or more disks. But again, the initial VM is deployed with the default datastore policy, and then converted to the desired policy. Not ideal, as it incurs overhead to change the layout of the objects.

PS C:\Users\chogan> New-VM -Name 30julytest6 -Template win7-desktop-orig2  -Datastore \
vsanDatastore -ResourcePool CH-Cluster  -OSCustomizationSpec win7 -AdvancedOption \
(Get-SpbmStoragePolicy RAID-5) | %{(@() + (Get-HardDisk -VM $_) + $_)} | \
Set-SpbmEntityConfiguration -StoragePolicy RAID-5

Entity                 Storage Policy                 Status          Time Of Check
------                 --------------                 ------          -------------
Hard disk 1            RAID-5                         compliant       7/31/2018 8:56:31 AM
30julytest6            RAID-5                         compliant       7/31/2018 8:56:35 AM


PS C:\Users\chogan> New-VM -Name 30julytest5 -Template win7-desktop-orig -Datastore \
vsanDatastore -ResourcePool CH-Cluster  -OSCustomizationSpec win7 -AdvancedOption \
(Get-SpbmStoragePolicy RAID-5) | %{(@() + (Get-HardDisk -VM $_) + $_)} | \
Set-SpbmEntityConfiguration -StoragePolicy RAID-5

Entity                 Storage Policy                 Status          Time Of Check
------                 --------------                 ------          -------------
Hard disk 1            RAID-5                         compliant       7/31/2018 8:31:56 AM
Hard disk 2            RAID-5                         compliant       7/31/2018 8:32:02 AM
30julytest5            RAID-5                         compliant       7/31/2018 8:32:07 AM

PS C:\Users\chogan>

Summary

While it is possible to create a single line command to create a VM with a certain storage policy, but if that VM is cloned from a Template, the command is not intuitive. Kudos once again to Manish Tiwari who helped significantly with the more advanced commands. I am going to request that this process for cloning a VM from a Template with a policy gets simplified, and that some simpler PowerCLI commands should be available to simplify the creation of all VM objects with the same policy when it is cloned from a Template.