Lab Ops 4–Using PowerShell with Storage

In previous posts I created a fileserver for my lab environment and used the UI to create a storage space on it.  Now I want to automate the creation of two storage spaces over the same storage pool, which will then underpin my VDI demos. At the time of writing the only resource I could find was on Jose Barreto’s blog.

Before I get to the PowerShell this is a quick sketch of how my file server is going to be configured..


My VM already has 6 virtual hard disks attached from my last post - 1x IDE for the operating system and the other 5 are scsi disks.  Two of these scsi disks are 50Gb in size the rest are 1Tb.

On top of this I want to create a pool “VDIPool” onto which I will put two storage spaces (virtual disks).  The dedup space at the top will have a one partition (X:) volume which will be setup for VDI deduplication while the normal volume/partition (N:) on the normal space won’t have this enabled but will be identical in size and configuration.  Both volumes will then have shares setup on them to host the VDI virtual machines templates and user disks.

All of this only takes a few of lines of powershell (less if you don’t like comments and want your command all on one line!) ..


$FileServer = "FileServer1"
$PoolName = "VDIPool"
$SpaceName1 = "DedupSpace"
$SpaceName2 = "NormalSpace"

#1. Create a Storage Pool
$PoolDisks = get-physicaldisk | where CanPool -eq $true
$StorageSubSsytem = Get-StorageSubSystem
New-StoragePool -PhysicalDisks $PoolDisks -FriendlyName $PoolName -StorageSubSystemID $StorageSubSsytem.UniqueId

#2. tag the disks as SDD,HDD by size
# note to get the actual size of disks use (physicaldisk).size

Get-PhysicalDisk | where size -eq 1098706321408 | Set-PhysicalDisk -MediaType HDD
Get-PhysicalDisk | where size -eq 52881784832 | Set-PhysicalDisk -MediaType SSD

#3. Create the necessary storage tiers
New-StorageTier -StoragePoolFriendlyName $PoolName -FriendlyName "SSDTier" -MediaType SSD
New-StorageTier -StoragePoolFriendlyName $PoolName -FriendlyName "HDDTier" -MediaType HDD

#4. Create a virtual disk to use some of the space available
$SSDTier = Get-StorageTier "SSDTier"
$HDDTier = Get-StorageTier "HDDTier"

#5. create two Storage spaces
New-VirtualDisk -FriendlyName $SpaceName1 -StoragePoolFriendlyName $PoolName -StorageTiers $HDDTier,$SSDTier -StorageTierSizes 1Tb,30Gb -WriteCacheSize 2gb -ResiliencySettingName Simple
New-VirtualDisk -FriendlyName $SpaceName2 -StoragePoolFriendlyName $PoolName -StorageTiers $HDDTier,$SSDTier -StorageTierSizes 1Tb,30Gb -WriteCacheSize 2gb -ResiliencySettingName Simple

#6. create the dedup volume and mount it
$VHD = Get-VirtualDisk $SpaceName1
$Disk = $VHD | Get-Disk
Set-Disk $Disk.Number -IsOffline 0
Initialize-Disk $Disk.Number -PartitionStyle GPT
New-Partition -DiskNumber $Disk.Number -DriveLetter "X" -UseMaximumSize
Initialize-Volume -DriveLetter "X" -FileSystem NTFS -NewFileSystemLabel "DedupVol" -Confirm:$false
#note -usagetype Hyper-V for use in VDI ONLY!
Enable-DedupVolume -Volume "X:" -UsageType HyperV

#7. create the non dedup volume and mount it
$VHD = Get-VirtualDisk $SpaceName2
$Disk = $VHD | Get-Disk
Set-Disk $Disk.Number -IsOffline 0
Initialize-Disk $Disk.Number -PartitionStyle GPT
New-Partition -DiskNumber $Disk.Number -DriveLetter "N" -UseMaximumSize
Initialize-Volume -DriveLetter "N" -FileSystem NTFS -NewFileSystemLabel "NormalVol" -Confirm:$false

#8. create the standard share directory on each new volume
md X:\shares
md N:\shares

#9. Get a template ACL for the folder we just created and add in the access rights
# need to use the share for VDI VMs (Note there are too many permissions here!)
# and set up an ACL to be applied to each share

$ACL =Get-Acl "N:\shares"
$NewRights = [System.Security.AccessControl.FileSystemRights]::FullControl
$NewAcess = [System.Security.AccessControl.AccessControlType]::Allow
$InheritanceFlags = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit"
$PropogationFlags = [System.Security.AccessControl.PropagationFlags]::None

$AccountList = ("Contoso\Administrator","CREATOR OWNER", "SYSTEM","NETWORK SERVICE", "Contoso\Hyper-V-Servers")

Foreach($Account in $AccountList)
$NewGroup = New-Object System.Security.Principal.NTAccount($Account)
$ACE = New-Object System.Security.AccessControl.FileSystemAccessRule ($NewGroup, $NewRights,$InheritanceFlags,$PropogationFlags,$NewAcess)
Write-Host "ACE is " $ACE
#10. Now setup the shares needed for VDI pool
# one for the VMs and one for the user disks
# on each of the volumes

$SMBshares = ("DedupVMs","DedupProfiles","NormalVMs","NormalProfiles")
foreach($Share in $SMBshares)
if($Share -like "Dedup*")
$SharePath = "X:\shares\" + $Share
md $SharePath
New-SmbShare -Name $Share -Path $SharePath -CachingMode None -FullAccess contoso\Orange$,contoso\administrator
Set-Acl -Path $SharePath -AclObject $ACL
if($Share -notlike "Dedup*")
$SharePath = "N:\shares\" + $Share
md $SharePath

New-SmbShare -Name $Share -Path $SharePath -CachingMode None -FullAccess contoso\Orange$,contoso\administrator
Set-Acl -Path $SharePath -AclObject $ACL


  • Get-storagesubsytem returns fileserver 1 storage spaces on my demo rig
  • Using PowerShell to create storage spaces gives you access to a lot of switches you don’t see in the interface like setting the cache size
  • when you create a storage space, it’s offline so you have to bring it online to use it.
  • Apart form disabling the cache on an SMB share I couldn’t see what other setting to configure the share as an application share – My test share in the screenshot above was created by using Server Manager to create an application share – a special kind of share in Windows Server 2012 for hosting databases and Hyper-V virtual machines

Having run this I can now see my shares in server manager


This script is designed to be run on Fileserver1, whereas the script to create the VM itself can be run from anywhere so what I want to do is to run this script remotely on that VM and the way to do that is:

invoke-command -computername FileServer1 -filepath “e:\powershell\FileServer1 Storage Spaces.ps1”

..where FileServer1 Storage Spaces.ps1 is my script.  BTW I can apply a script like this to multiple servers at the same time by substituting FilerServer1 with a comma separated list of servers.

Next time I want to go into what exactly is going on in the script to create an SMB share and assign access rights to it (steps 9 and 10) as I found this quite hard to research. and so perhaps I can help to make this easier for you and as an aide memoire for me!

As I have mentioned before there isn’t an evaluation edition available just yet, so if you want to try this now you should find it will work from the Windows Server 2012 R2 preview, although you will still have to inject the license key in your scripts at some point to fully automate vm creation.