Insufficient data from Andrew Fryer

The place where I page to when my brain is full up of stuff about the Microsoft platform

October, 2013

  • Lab Ops - Stop Press Windows Server 2012R2 Evaluation edition released

    I have just got back to my blog after a few days at various events and I see the Evaluation edition of Windows Server 2012R2 has been released.  I need this for my lab ops because I am building and blowing away VMs for er… evaluations and I don’t want to have to muck about with license keys. For example I have a script to create FileServer1 VM but if I use the media from MSDN for this and I don’t add in a license key to my answer file, the machine will pause at the license key screen until I intervene.  Now I have the Evaluation Edition I can build VM’s that will starter automatically and when they are running continue to configure them. For example for my FileServer1 VM I created in earleir posts in this series  I can add a line to the end of that script while will run on the VM itself once it is properly alive after its first boot..

    invoke-command -ComputerName $VMName -FilePath 'E:\UK Demo Kit\Powershell\FileServer1 Storage Spaces.ps1'
    ..and this will go away and setup FileServer1 with my storage spaces.

    Note both the script to create FileServer1 (FileServer1 Setup.ps1) and the xml it uses to add features into that VM (File server 1 add features.xml) and the File Server1 Storage Spaces.ps1 script referenced above are on my SkyDrive for you to enjoy.

    One good use case for executing remote PowerShell  scripts remotely like this is when working on a cluster. Although I have put the Remote Server Administration Tools (RSAT) on my host and to have access to the Failover Clustering  cmdlets I get a warning about running these against a remote cluster..

    WARNING: If you are running Windows PowerShell remotely, note that some failover clustering cmdlets do not work remotely. When possible, run the cmdlet locally and specify a remote computer as the target. To run the cmdlet remotely, try using the Credential Security Service Provider (CredSSP). All additional errors or warnings from this cmdlet might be caused by running it remotely.

    While on the subject of new downloads the RSAT for managing Windows Server 2012R2 from Windows 8.1 is now available, so you can look after your servers from the comfort of Windows 8.1 with your usual tools like Server Manager, Active Directory Administrative Console, Hyper-V manager and so on On my admin VM I have also put on the Virtual Machine Manger Console ad SQL Server Manager and a few other admin tools..



    Before you ask me the RSAT tools you put on each client version of Windows only manage the equivalent version of server and earlier.  For example you can’t put the RSAT tools for managing Windows Server 2012R2 onto Windows 8 or Windows 7.

    So using my lab ops guides or the more manual guides on TechNet, you can now get stuck into playing with Windows Server 2012R2, as a way of getting up to speed on the latest Windows Server along with the R2 courses on the Microsoft Virtual Academy.

  • Lab Ops 7 – Setting up a pooled VDI collection in Windows Server 2012 R2

    In Windows Server you can create two kinds of Virtual Desktop Infrastructure (VDI), personal or pooled.  A personal collection is a bit like a company car scheme where everyone chooses their own car. This means there needs to be car for everyone even if they are on leave or sick etc. and each car needs to be individually maintained. However the employees are really happy as they can pimp their transport to suit their own preferences.  Contrast that with a car pool of identical cars, where an employee just takes the next one out of the pool and when its brought back its refuelled and checked ready for the next user, and you don’t need a car for everyone as there’ll be days when people just come to the office or use public transport to get to their destination.  That seems to be a better solution than company cars for the for the employer but not so good for the employees. Pooled VDI collections work like pool cars in that they are built from one template and so only one VM has to be maintained, but that means every user has the same experience which, might not be so popular.  However Pooled VDI in Windows Server 2012 has a method for personalising each users experience while still offering the ability to manage just one template VM and that’s why I want to use pooled VDI in my demos. 

    Carrying on from my last post I right click on RD Virtualisation Host and select Create Virtual Desktop Collection


    Now I get specify the collection type

    vdi collection type


    Having chosen the collection type I now need to pick a template on which to base the pool..

    vdi template selection

    I found out that you can’t use the new Hyper-V generation 2 VMs as a VDI template even in Windows Server 2012R2 rtm. This does mean you can use that WimtoVHD Powershell script I have promoting in earlier posts in this series to create my template directly from the Windows installation media. 

    Note: you’ll need windows 8.1 enterprise for this which is currently only available on msdn, until 8.1 is generally available in a couple of weeks when there should be an evaluation edition available

    In fact for a basic VDI demo the VHD this creates can be used as is; all you need to do is create a new VM from this VHD to be configured with the settings each of the VDI VMs will inherit, such as CPU, dynamic memory settings, Virtual NICs and which virtual switches they are connected as well as any bandwidth QoS you might want to impose..  

    vdi template details

    Here you can see the setting for my template VM such as it being connected to my FabricNet virtual switch.

    Normally when you build VMs from templates you will want to inject an unattend.xml file into the image to control its settings as it comes out of  sysprep (as I have done in earlier posts in this series). This wizard helps you with that or you can just enter basic settings in the wizard itself as I have done ..

    vdi template settings

    and not bother with an unattend.xml file at all.


    vdi template unattend settings

    Now I can start to configure my collection by giving it a name, how many VMs it will contain and specifying who can access it ..

    vdi create collection

    In a production environment you would have several virtualization hosts to run your collection of VMs and here you can specify the load each of those hosts will have. 

    vdi specify hosts for collection

    Having specified which hosts to use I can now get into the specifics of what storage the VMs will use. I am going for a file share, specifically one of the file shares I created earlier in this series, which will make use of the enhancements to storage in R2.  Note the option to store the parent disk on a specific disk, which might be a good use of some of the new flash based devices as this will be read a lot but rarely updated.

    vdi vm location

    My final choices is whether to make use of user profile disks.  This allows all a users settings and work to be stored in their own virtual hard disk and whenever they log in to get a pooled VM, this disk is mounted to give them access to their stuff.  This is really useful if all your users only ever use VDI as you don’t need to worry about all that roaming profiles and so on.  However if your users sometimes use VDI and sometimes want to work on physical desktop such as laptops then you’ll want to  make use of the usual tools for handling their settings across all of this so they get the same desktop whatever they use - remember we work for these people not the other way around! 

    vdi user profile disk location 

    That’s pretty much it - the desktops will build and your users can login via the web access server in my case by going to

    To demo the differences in performance on a pooled VDI collection that sits on a storage space that's had deduplication enabled I could create another collection on the Normal* shares I created in my post on storage spaces by doing this all again.  Or I could just run a PowerShell command, New-RDVirtualDesktopCollection,  and set the appropriate switches..

    $VHost = ""
    $RDBroker = ""
    $ColectionName = "ITCamps"

    #The VDI Template is a sysprepped VM running the Virtual Hard Disk, network settings etc.  that all the pooled VMs will inherit.  The VHD will run windows 8.1 configured and sysprepped with any applications and setting needed by end-users

    $VDITemplateVM = get-vm -ComputerName $VHost -Name "Win81x86 Gen1 SysPrep"

    New-RDVirtualDesktopCollection -CollectionName "ITCamp" -PooledManaged -StorageType CentralSmbShareStorage -VirtualDesktopAllocation 5 -VirtualDesktopTemplateHostServer $VHost -VirtualDesktopTemplateName $VDITemplateVM -ConnectionBroker $RDBroker -Domain “” -Force -MaxUserProfileDiskSizeGB 40 -CentralStoragePath”\\fileserver1\NormalVMs” -VirtualDesktopNamePrefix "ITC" -OU “VDICampUsers” -UserProfileDiskPath “\\fileserver1\NormalProfiles”
    My good friend Simon May then gradually add in more and more VMs into the collection with the Add-RDVirtualDesktopToCollection cmdlet to see how much space he can save.

    The other really clever thing about a pooled VDI setup like this, is maintaining it.  Clearly you will want to change the tem[plate the Pooled collection is based on from time to time, for example to add or remove version of applications and to keep patches up to date.  All you have to do is to make another template VM with the new applications and latest patches and then   Update the collection from the Collection management screen, or via the Update-RDVirtualDesktopCollection PowerShell cmdlet for example

    PS C:\> Update-RDVirtualDesktopCollection -CollectionName "ITCamp" VirtualDesktopTemplateName "$VDITemplateName" -VirtualDesktopTemplateHostServer $VHost -ForceLogoffTime 12:00am -DisableVirtualDesktopRollback -VirtualDesktopPasswordAge 31 -ConnectionBroker $RDBroker

    where I would have set $VDITemplateName to be the modified and sysprepped VM to base the updated collection on. Note the Force LogOffTime setting; that’s where users will be thrown out and forced to log on again.  If you don’t set this they’ll only get to use the new version when the login and logout again.  However you manage that if you have used User Profile in the collection as I have done their preferences and setting will persist on the updated collection.


    So that’s the basics of setting up VDI on a laptop for your evaluations.  From here I could go on to ad other parts of the Microsoft remote desktop solution such as;

    • Set up RemoteApp the business of delivering individual applications over the Remote Desktop Protocol (RDP)
    • Add in RD Session Hosts and RDS Collections to deliver the traditional terminal services functionality and still the most efficient way to deliver remote desktops top users
    • Add in an RD Gateway to open up the RD infrastructure to remote users.  Clever use of the Remote Routing and Access Services role in a VM that’s connected to virtual networks can be used to simulate this connectivity from just one host. 
    • Add in a Licensing host for production environments 

    However I would be interested to know what you would like me to post next, so please add comments or if you are shy e-mail me

  • Lab Ops 6 – Setup VDI in Windows Server 2012R2

    VDI bridges the world of the client and the server, and that can mean that in a world where IT professionals are either experts in one or the other (Simon and I being  a case in point), most of us have a partial knowledge of how VDI works.

    There are other reasons why you might be forgiven that VDI isn’t a Microsoft strength for two reasons:

    • It has been hidden behind offerings from third parties like Citrix, and those partners are still important for larger implementations and because in the past those partners made the only decent remote desktop clients for all sorts of platforms such as Android and IOS.  That all changed on 7th October and to quote the official press release:

    “.. with Windows Server 2012 R2 Microsoft is introducing the Microsoft Remote Desktop app, available for download in application stores later this month, to provide easy access to PCs and virtual desktops on a variety of devices and platforms, including Windows, Windows RT, iOS, OS X and Android.”

    • VDI isn’t referred to as such in TechNet or in the Windows Server interfaces such as Server Manager as VDI – it’s called Remote Desktop Services which also includes the traditional terminal services way of providing a remote desktop, but also includes using pooled or  personal client VMs as well.

    However since Windows Server 2012 it has been pretty easy to setup a secure and resilient VDI environment just using Windows client and server, that offers your users a rich and personalised experience.

    So before I go into how to build a lab what are the moving parts?  The easiest way to see this is post deployment as there’s an overview in server manager..

    VDI Overview

    The green objects have yet to be configured; The RD Gateway for external access to my VDI environment and the licensing server. 

    The grey objects are configured and go blue when in hover on them:

    • the RD Web Access Server is the web server that users connect in from.
    • The RD Connection Broker is the middle tier which orchestrates the whole setup; what servers are performing which functions, where the VDI VMs are to control their state , and handling security to limit who can access which desktop and applications.
    • The RD Virtualization Host are the physical server(s) that that the VDI VMs run from.
    • Optionally there is also an RD Session Host for  Remote Desktop Services (Terminal Services as was)

    Notice the IT Camp collection. A collection is a pool of client VMs. The idea is to manage the collection as one VM and I’ll describe the options and how to configure collections in my next post. 

    One thing to note about RDS/VDI is that highly availability (HA) is going to be very important as no one will get any work done if there are no desktop to work on. For this reason my lab setup needs to be tagged with “don’t try this at work!” Of course there’s no point in evaluating this unless you are sure that you can enable HA and this is the sort of setup that would allow for that..


    • The web access servers need to be load balanced as for any web site
    • The broker role can be clustered and not the use of SQL Server to store metadata about the environment when this is the case. Of course that SQL Server database would need to reside on resilient shared storage or it becomes a single point of failure.  Also note that Broker1 and Broker 2 can handle connection requests i.e. this is an active active scenario and that’s why there’s a shared database in the mix.
    • The virtualization hosts have no special settings for HA it’s just that there’s more than one of them and typically you’ll want to ensure you have enough spare server resources to able to run your collection of VMs if one of the servers is not longer available. 
    • The VMs virtual hard disks could be on shared storage but actually this doesn’t matter too much, what matters is where the user’s data is and the parent disk of the VDI collection. RDS in Windows Server 2012 has special user profile disks and it is these that should be on shared storage and when you configure RDS you get to specify where these are stored as distinct from the virtual hard disks for each VDI VM.   

    At this point you might be wondering what happens if one of the Virtualization Hosts fails.  It’s really simple - for those users that had open desktops that were based on VMs on that failed server, then those users will loose their session.  However given that the shared storage behind all of the VMs is still there then when the user connects in again they won’t have lost any saved work. So a bit like a real desktop crash except that they can immediately sign back in and continue where they left off as the broker will assign them an unused VM on a running server, and that will be quick as the VDI VMs are left in a saved state to be ready for immediate use

    Anyway on with my lab setup which builds on earlier posts in this series..

    As I’ve already said I need at least one physical host to be the RD Virtualization Host and my laptop in the diagram above is the “Orange” session host. The other roles in the diagram above can all be one or more VMs themselves and those roles can be combined.  A production environment will need to have use multiple VMs on different hosts but you might not need to scale out the roles to dedicated VMs in smaller deployments.

    For my demo I am going to use a VM for the Broker role (RDBroker) , another for Web Access (RDWebAccess) and a third as a Session Host (RDSHost). To create all of these vms I have adapted the setup scripts described in part 2 of this series so I can create these with a line of PowerShell for each..

    Create-VM -Name RDWebAccess -VmPath ($labfilespath) -SysPrepVHDX ("E:\WS2012RTM SysPrep.VHDX") -Network "FabricNet" -VMMemory 2GB -UnattendXML $unattendxml -IPAddr "" -DnsSvr "" -Domain ""
    Create-VM -Name RDBroker -VmPath ($labfilespath) -SysPrepVHDX ("E:\WS2012RTM SysPrep.VHDX") -Network "FabricNet" -VMMemory 2GB -UnattendXML $unattendxml -IPAddr "" -DnsSvr "" -Domain ""
    Create-VM -Name RDSHost -VmPath ($labfilespath) -SysPrepVHDX ("E:\WS2012RTM SysPrep.VHDX") -Network "FabricNet" -VMMemory 2GB -UnattendXML $unattendxml -IPAddr "" -DnsSvr "" -Domain ""     
    Note: My sysprepped image used to create these vms is based on the download from msdn , so I am asked for a license key which I can skip, but it’s a manual step. When an evaluation edition of Windows Server 2012 R2 is available this won’t be a problem.

    I can now configure these blank vms through Server Manager from one machine, provided you have already added them as servers to be managed as I have (the servers in the yellow box)..


    The first step is to add the roles and features to each of my server VMs, and since Windows Server 2012 this has been a special installation option, Remote Desktop Services Installation.  As I mentioned before Remote Desktop Services is a generic term in Windows Server to cover both VDI and Remote Desktop Sessions (what was terminal services). and so the wizard asks you which one you want.  For this post I am going for VDI. In the following screens for this wizard I can assign each role to one of my servers and the wizard will deploy the whole environment for me, and then show me that overview screen at the start of this post.

    There’s a couple of things you’ll want to check before you actually create a VDI collection:

    Check the Deployment settings:


    For example you can add in your licensing server, specify the Web Access URL to use and in my case I don’t the export location for my template to be on the the RDBroker server as it’s a VM so I’ll use a share somewhere else.  You’ll also want to setup certificates for this, and when I have that properly researched I’ll cover it off in this series.

    Increase the VM Build Concurrency on your Hosts

    By default Hyper-V builds VMs one at a time which might be a good if cautious move for heavily used production hosts but on my laptop(s) I want to up this, and this is the PowerShell to hack the appropriate registry setting and reboot the hosts for this to take effect..

    #replace “server1”,”server2” with your list of servers

    $CompNames =@("Server1",”Server2”)

    foreach ($CompName in $CompNames)
         Invoke-Command -ComputerName $CompName -ScriptBlock {

        Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\VmHostAgent\Parameters"`
          -Name "Concurrency" -value 5
         Restart-Computer -force}

    Now I am ready to build “collections” of virtual machines and that’s coming up in the next post.

  • Lab Ops 5 - Access Rights in PowerShell

    In my last post I had a section in my script to create access right to a share I had just created and as promised I wanted to dissect that a bit more.

    To recap what I wanted to do was to create a share with sufficient privileges to use that share for storing VMs as part of my VDI demo. In order to understand what permissions might be needed I used the wizard in Server manager to create a share (FileServer1\\VMTest), checked that I could use the Remote Desktop Services part of Server Manager to successfully create a pooled VDI collection and then examine its permissions.

    The share has everyone full control access..

    Share settings

    and these are the File Access Rights on that share..

    Share secirity settings

    The SMB settings are set by the -fullAccess, for example in my script

    #Orange$ is the name of the physical host (my big orange Dell Precision laptop)

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

    The Access Rights are stored in Access Control Lists (ACLs) comprising individual Access Control Entries (ACEs) where an entry might state the contoso\Andrew has full control of a path and its folders and subfolders.  Out of the box in PowerShell there are just two command involved get-ACL to get this list and Set-ACL to modify setting on a path.  TechNet recommend that you create a share (say x:\test) set up its permissions and pass this across to your new share

    Get-Acl -path “X:\Test” | Set-Acl -path “ X:\My New Share”

    which is fine but in my case I am building a setup form scratch and I don’t wan to have to use an interface to create the template.  So it occurred to me I could write the ACL out to a file with one row per ACE and here’s my script to get the ACL for that VMTest share in the above screenshot..

    #to a CSV for later use
    $CSVFile = \\Orange\E`$\UK Demo Kit\Powershell\FileShareACL.CSV

    #If the file is already there delete it
    If(Test-Path $CSVFile) {Remove-Item $CSVFile}
    $Header = "Path|IdentityReference|FileSystemRights|AccessControlType|IsInherited|InheritanceFlags|PropogationFlags"
    Add-Content -Value $Header -Path $CSVFile
    $TemplatePath = "X:\shares\VMTest"
    $ACLList = get-acl $TemplatePath | ForEach-Object {$_.Access}
    foreach($ACL in $ACLList)
        $LineItem = $TemplatePath+ "|" + $ACL.IdentityReference + "|" +  $ACL.FileSystemRights + "|" + $ACL.AccessControlType + "|" + $ACL.IsInherited + "|" + $ACL.InheritanceFlags + "|" + $ACL.PropogationFlags
        Add-Content -Value $LineItem -Path $CSVFile

    The Add-Content command allows me add write into a file, but not that alothough I have specified this as a CSV file it is in fact pipe (“|”) delimtied because it’s generally madness to use commas as separators as they get used inside the values as in this case..

    X:\shares\VMTest|BUILTIN\Administrators|FullControl|Allow|True|ContainerInherit, ObjectInherit|
    X:\shares\VMTest|NT AUTHORITY\SYSTEM|FullControl|Allow|True|ContainerInherit, ObjectInherit|
    X:\shares\VMTest|CREATOR OWNER|268435456|Allow|True|ContainerInherit, ObjectInherit|
    X:\shares\VMTest|BUILTIN\Users|ReadAndExecute, Synchronize|Allow|True|ContainerInherit, ObjectInherit|

    so Inheritance flags and access rights can have multiple values inside one ACE.  While there are several examples of this sort of script out there I had to do some digging to find out how to use this file, So here’s my crude but effective attempt..

    $ACEList = Import-CSV -Path "\\orange\E`$\UK Demo Kit\Powershell\FileShareACL.CSV" -Delimiter "|"
    $TestPath = "C:\Test"
    If (test-path -Path $TestPath) {Remove-item -Path $TestPath}
    MD $TestPath
    $ACL = Get-Acl -Path $TestPath
    ForEach($LineItem in $ACEList)
        If($LineItem.FileSystemRights -eq 268435456) {$LineItem.FileSystemRights = "FullControl"}
        If($LineItem.FileSystemRights -eq "ReadAndExecute, Synchronize"){$LineItem.FileSystemRights = "ReadAndExecute"}
        $NewRights = [System.Security.AccessControl.FileSystemRights]::($LineItem.FileSystemRights)
        $NewAcess = [System.Security.AccessControl.AccessControlType]::($LineItem.AccessControlType)
        $InheritanceFlags = [System.Security.AccessControl.InheritanceFlags]($LineItem.InheritanceFlags)
        $PropogationFlags = [System.Security.AccessControl.PropagationFlags]::None
        $NewGroup   = New-Object System.Security.Principal.NTAccount($LineItem.IdentityReference)
        $ACE = New-Object System.Security.AccessControl.FileSystemAccessRule ($NewGroup, $NewRights,$InheritanceFlags,$PropogationFlags,$NewAcess)
        Set-Acl -Path $TestPath -AclObject $ACL

    While this not be a solution for you it does show up some interesting points in PowerShell and in setting security:

    • There’s no command to make a new ACL you have to start with one from somewhere
    • Once I have declared $AceList as my csv file it is that file. For example I can get PowerShell to display it an all its glory using $ACEList | out-gridview to see it as a table
    • I have declared the separator I used to get round the comma problem with the -Delimiter “|” setting
    • I can loop through each line of my file with a simple foreach loop and so $LineItem represents each line and I can references the columns in that line with the standard . notation used in .Net e.g. $LineItem.FileSystemRights.
    • The stuff in square brackets might look hard to remember but PowerShell will auto complete this so once I typed in [System. I could select Security and so on to build up the correct syntax.
    • I have marked a line in my csv file in red because the File System Rights are set to a number in my case 268435456.  This is an example of an Access Control mask a set of bits that will cause an error when I try and create $ACE, so I have an exception in my code (also in red) to trap that and in my case just assign full control.
    • There is a another problem line marked in purple in my csv and that’s because this also threw an error.  I looked up the synchronize option and realised it gets set by default and so I put in another exception in y script (in purple) to trap that and just apply ReadAndExecute rights.
    • I had to refer to the .Net documentation here to work out what order to put the parameters in to create a new ACE (the line beginning $ACE = New-Object…)
    • Having built up the ACL in the loop it’s really easy to apply it your object ands of course this could be used for multiple objects in another loop for that

    So what I have done here is a bit of a sledgehammer to crack a nut, but you might be able to use some of the principles to solve your real world problem for example you might just knock up a CSV file with permissions you want to set on an object.

    Finally there’s this properly tested File System Security PowerShell Module on the TechNet gallery although it’s not yet been tested on Windows Server 2012 or R2. 

  • 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.








  • Lab Ops part 3 – Storage in Windows Server 2012R2

    In this post I want to show what I plan to do with storage in Windows Server 2012R2 at the various events I get asked to present at.  If you have been to any of our IT Camps you will have seen Simon and I show off deduplication and storage spaces in Windows Server and now I want to add tiered storage into the mix - and I have a cunning plan.  This is to declare some of my storage as hard disk and other parts as SSD.

    Before I get to that I need to create a File Server v. To do that I have adapted the setup script from Marcus I have posted previously to create this vm.  All I needed to do after the VM was created was to add in the fileserver roles and role features I needed.  The easiest way to do that is use the UI to add in the necessary features and then save them off to an xml file..

     add fileserver features

    as the screentip above shows I can then consume this xml file to add in the features to my fileserver vm everytime I create it

    Install-WindowsFeature -Vhd $VHDPath -ConfigurationFilePath "E:\scripts\file server 1 add features.xml" -ComputerName "Orange"
    where the –computername setting is my physical host as I am mounting the VHD off line to add the features before it starts

    Now I can use this vm to show tiered storage and there are two parts to this:

    • Create some virtual disks and set them up to emulate the performance of the two different types of disk.  In Server 2012R2 there are advanced properties of virtual hard disks for Quality of Service (QoS), which are exposed in Hyper-V Manager, Virtual Machine Manager and of course PowerShell..

    #note the MaximumIOPs settings

    for ($i = 1; $i -le 3; $i++)
        $VHDPath = $labfilespath + "\" + $VMName + "\"  +"SCSI" + $i +".vhdx"
        New-VHD -Dynamic -Path $VHDPath -SizeBytes 1tb
        Add-VMHardDiskDrive -VMName $VMName -Path $VHDPath -ControllerType SCSI    -ControllerLocation $i -MaximumIOPS 100
      for ($i = 4; $i -le 5; $i++)
        $VHDPath = $labfilespath + "\" + $VMName + "\"  +"SCSI" + $i +".vhdx"
        New-VHD -Dynamic -Path $VHDPath -SizeBytes 50gb
        Add-VMHardDiskDrive -VMName $VMName -Path $VHDPath -ControllerType SCSI -ControllerLocation $i -MaximumIOPS 10000
    To identify which disk is which in the VM for my demo – remember I want to use the UI to show this being setup as PowerShell scripts aren’t great for explaining stuff.  To this I tried to tag my disks as HDD or SSD now they are inside the VM.  using

    Set-PhysicalDisk  –MediaType1

      where media type can be SSD or HDD. My plan was to base this on the size of the disks (My notional hard disks are 1Tb above as opposed to just 50Gb for the SSD. However you can’t use this command until you have created a storage pool so I will keep this code for later run it interactively

    To stress my tiered storage and to show off deduplication in Windows Server 2012R2 I plan to use this storage as the repository for my VDI vms. In order to that I have to do the following things beforehand:

    1. Use the storage to create the pool. From Server Manager


    by right clicking on the primordial row in storage spaces, giving my poll a name and selecting all those blank scsi disks I created..


    and clicking create (Note I have left all the disks set to automatic for simplicity)

    2. Tag the disks as SSD/HDD in order to tier the storage

    I just use the PowerShell above to do this based on size of the disks..

    #note to get 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

    Checking back in server manager I can see the media type has been set and you can now see my VDI Pool..


    3. Create a virtual disk over the storage pool. 

    Storage spaces are actually virtual hard disks and so from the screen above I select New Virtual Hard Disk from the tasks in Virtual Disks pane and select the storage pool I have just created.  I then get the option to use the new tiered storage feature in Windows Server 2012R2..


    I’ll select simple in the next screen to stripe my data across the disks in the pool. In the next screen the option to thin provision the storage is greyed out because I have selected tiered storage, which isn’t a problem for my lab as this pool is built on disks which are in fact virtual disks themselves but be aware of this in production. Just to be clear you can either create a storage space (VHD) that is thin provisioned beyond what you have available now OR you can commit to a fixed size and use tiered storage.

    Now I get another new (for R2) screen to set the size of my VHD based on how much of the pool I want to use.  I am going to use 30gb of SSD and 1Tb of HDD.


    I am then get asked to format the VHD and mount it.  I mount it as drive V and give I the name VDIStorage.  In the final step I can enable deduplication..

    imageNote I have the option to use deduplication for VDI in Windows Server 2012R2 so I will go for that.  The wizard will then guide me through formatting and mounting this VHD so it can now be used as a storage space

    Now I am ready to configure VDI . But what if I wanted to do all of that in PowerShell? Well I am going to leave that for next time as this is already a pretty long post.

    In the meantime if you have an MSDN subscription then you can get the rtm version of Windows Server 2012R2 and follow along. If not I am sure there’ll be an evaluation copy coming it in a few weeks to coincide with the general availability of R2, and in the mean time check out the Windows Server 2012R2 jumpstart module on MVA.   

    1Keith Meyer one of my counterparts has more on all of this in this excellent post.