This article describes how to build a Windows Server 2016 Storage Spaces Direct virtual lab, step-by-step on a Windows 10 desktop or laptop PC. This virtual lab environment is capable of emulating a complete cluster of storage servers, each with six directly attached virtual disk drives. Since Windows 10 and Windows Server 2016 now support nested Hyper-V, each virtual server can also run the Hyper-V role and host application workload VMs.
Virtual Lab Overview
The virtual lab will contain the following components:
- An Active Directory Domain Services VM dedicated to this environment
- Four Storage Server VMs
- A Virtual Switch for the Management Network
- A Virtual Switch for the Provider Network subnet
In the diagram below (click to zoom in) the workstation has the Hyper-V role installed and has a group of Virtual Machines providing both Active Directory and Hyper-Converged Storage services.

The screenshot below is the Hyper-V Manager running on the completed lab workstation with a group of Virtual Machines.

The functions of each virtual machine shown in the screenshot below are:
- AD1 – A Windows Server 2016 VM providing AD DS services
- Storage1-4 – Windows Server 2016 core VMs with attached Virtual Hard Disks emulating four storage servers with locally attached disk drives. These VMs can be either a dedicated storage cluster or a hyper-converged cluster.
- Win2016-Core-Template The template VM is used as a template to build server VMs.

Deploying the Virtual Lab
This section covers the creation of the virtual lab and will consist of the following steps:
- Install the Hyper-V role on the lab workstation or server
- Create the Management Hyper-V Virtual Switch
- Create the Provider Hyper-V Virtual Switch
- Build the Windows Server 2016 template VM
- Build the Storage Spaces Direct server VMs
System Requirements
The hardware requirements for the virtual lab are:
- A PC workstation with
- 16GB Memory and
- an SSD drive with 300GB of free space
- A Windows version capable of running the Hyper-V role
- Windows 10 (Pro or Enterprise) (not the Home version)
- Or Windows Server 2016 with Desktop Experience
- Up to date with Windows Updates
- 16GB Memory or greater
- One or more SSD drives with 300GB free space or greater
Windows software images:
- Windows Server 2016 ISO image file
Install Hyper-V role
The virtual lab can be hosted by either a Windows 10 or a Windows Server 2016 computer. Hyper-V is enabled differently depending on the version of Windows.
Windows 10 Hyper-V
Control Panel >> Programs and Features >> Turn Windows features on or off

- Enable the Hyper-V Management Tools and Platform.
- Enable Hyper-V role on Windows 10
The equivalent PowerShell command is
Enable-WindowsOptionalFeature -Online -FeatureName:Microsoft-Hyper-V -All
Windows Server 2016
Run the PowerShell command
Install-WindowsFeature –Name Hyper-V -IncludeManagementTools -Restart
Create the Hyper-V Switches
The two Hyper-V virtual switches are:
- Management – Deployment and management network. This network will interact with the host workstation network and external networks.
- Provider – This network is the core data center network and handles all storage, virtual machine, and cluster traffic.
Management Virtual Switch
From the Hyper-V Manager on the host workstation, go to the Virtual Switch Manager and create a new virtual switch with the following settings.
- Name: Management
- External Network
- Select the physical network adapter on the workstation which has Internet access
- This may be a wired network interface or a wireless interface
- Allow Management Operating to share the network adapter

Provider Virtual Switch
Create the provider virtual switch with the following settings.
- Name: Provider
- Select the Connection type: Private network

Build the Active Directory Domain Services VM
The Active Directory VM will be a dedicated server for this cloud environment. The example configuration parameters for this server are:
| Parameter | Value |
| Domain Name | Contoso.local |
| Computer Name | AD1 |
| Management Adapter IP Address | 10.0.0.100/24 |
| Role/Features | AD DS, DNS |
The IP address ranges used in these instructions are the same subnet as the Internet router. The Internet router address is 10.0.0.1. For your environment, this range will likely be different and you will need to make the appropriate adjustments.
Create a new virtual machine wizard
Follow the steps below using the Hyper-V Manager on the host workstation.
- Action >> New >> Virtual Machine
- Name: AD1
- Store the Virtual Machine path:
- In our example, we use E:VMsAD1 since the E: drive is an SSD
- (Select the SSD drive letter and folder where the VMs will reside)
- Select the Generation of VM (either works)
- Startup Memory: 1024MB
- Use Dynamic Memory
- Connect to the Management virtual switch
- Select 20GB as the Virtual Hard Disk size
- Begin Installing an operating system from a bootable CD/DVD by selecting the image file
- Browse to your Windows Server 2016 ISO file
Start and Configure the AD1 VM
- Connect the virtual console to the VM (right-click AD1 VM and select connect)
- Follow the Windows installation after selecting Windows 2016 Standard (Desktop Experience)
- Log into the new AD1 VM
- Rename the computer to AD1
Set the Management Adapter IP configuration
Follow these steps in the Change Adapter Settings, located here.
Control Panel > View Network Status and Tasks > Change Adapter Settings
- Rename the adapter to Management
- Set the IP Address to 10.0.0.100
- Set the Subnet to 255.255.255.0
- Set the Default GW to the IP address of your Internet router
Install the Active Directory Domain Services role
- Include the Management Tools (default)
- Once the step above has been completed, the Role Install of AD DS wizard will include a link to promote this server to a domain controller. Click on this link.
Configure Active Directory
- Deployment Configuration
- Select: Add new forest
- Enter the Domain name: Contoso.local (anything you like)
- And then Next
- Domain Controller Options
- Use the defaults and
- add a DSRM password (anything you like)
- and then Next
- DNS Delegation
- There will be a warning about DNS delegation, ignore this
- Do not create DNS delegation
- And then Next
- NetBIOS name
- NetBIOS name: Contoso (anything you like)
- And then Next
- Paths
- AD DS paths, take the defaults
- And then Next
- Review Options:
- Click Next
- Prerequisites Check:
- There will be some warnings – ignore
- Click Install
Save this VM to be used over and over!
The core server VMs will be created with an automation script. Save this VM to be used in other labs or to rebuild other labs. This will allow the testing of various functions and failure scenarios with the virtual lab.
Build the Server Template VM
We will build a Windows Server 2016 VM which will be copied and used to create additional VMs. This allows the lab to be created quickly with a script. The lab can then be deleted and recreated quickly and with little effort.
Create another VM similar to how the AD1 VM was built above.
- Use Hyper-V Manager to create a new Virtual Machine
- Select a unique VM name, such as “Win2016-core-datacenter”
- Select the Windows Server 2016 core data center version
- Update the Management network. Rename the VM adapter to Management
- Set the IP address to 10.0.0.10
- Set the DNS address to 10.0.0.100 (AD1)
- Apply the latest Windows updates, first by logging into the console and run SCONFIG
- Apply all the updates available
- Shutdown the VM. This VM VHD file will be copied from this location and used to create additional servers.
- Remember the complete path of the new VHDx file as this path will be required in the PowerShell commands below.
Build the Storage Server VMs
Building the Storage servers is cumbersome and labor-intensive. The following software scripts are provided to automate this process. The AD1 and Template VMs can be saved and reused. Being able to destroy the core servers and rebuild them easily is a critical requirement.
function New-vS2DNode
{
<#
.SYNOPSIS Create a virtual machine with attached virtual disks
.DESCRIPTION Describe the function in more detail
.EXAMPLE Give an example of how to use it
.EXAMPLE Give another example of how to use it
.PARAMETER poolname The computer name to query. Just one.
.PARAMETER computername The name computer name to query
#>
[CmdletBinding()]
param
(
[Parameter(
Mandatory=$True,
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True,
HelpMessage='- VMName ')]
[string]$VMName,
[Parameter(Mandatory=$True)]
[string]$VMPath,
[Parameter(Mandatory=$True)]
[string]$VHDTemplate,
[bool]$AddStorageDisks
)
begin
{
$ErrorActionPreference = "Stop";
Write-Verbose "Checking if Hyper-V is enabled"
$HyperV = Get-WindowsOptionalFeature -FeatureName Microsoft-Hyper-V-All -Online
if ($HyperV.State -ne "Enabled" )
{
Write-Error "Hyper-V must be enabled on this host - exiting"
Throw
}
Write-Verbose "Checking if VMPath [$VMPath] folder exists"
if (!( Test-Path $VMPath ))
{
Write-Verbose "Creating VMPath folder [$VMPath]"
New-Item -Path $VMPath -ItemType directory | Out-Null
}
Write-Verbose "Checking for adequate disk space to create server"
$Drive = (Get-Item $VMPath).PSDrive.Name + ":"
$DriveObj = (Get-WmiObject Win32_LogicalDisk -ComputerName 'localhost')| ? DeviceID -eq $Drive
Write-Verbose "Disk Space available [$DriveObj.FreeSpace]"
if ($DriveObj.FreeSpace -lt 5000000000)
{
Write-Error "Inadequate disk space to create Virtual Machine"
Write-Error "Server has less that 50GB available"
Throw
}
Write-Verbose "Checking if VM already exists"
$Exists = Get-VM -name $VMName -ErrorAction SilentlyContinue
if ($Exists) {
Write-Error "VM already exists in Hyper-V"
Throw
}
Write-Verbose "Checking if VMPath is empty"
if ( Test-Path $VMPath )
{
if( (Get-ChildItem $VMPath | Measure-Object).Count -ne 0)
{
Write-Error "VMPath folder contains data - exiting"
Throw
}
}
Write-Verbose "Checking if VHD Template exists"
if (!( Test-Path $VHDTemplate ))
{
Write-Error "VHDTemplate file not found - exiting"
Throw
}
Write-Verbose "Checking that Hyper-V Virtual Switch [Management] exists"
Get-VMSwitch -Name Management -ErrorAction SilentlyContinue | out-null
if ( $? -eq $false )
{
Write-Error "Hyper-V Virtual Switch [Management] not found - exiting"
Throw
}
}
process
{
function AddStorageDisks
{
###############################################################
# Create the Storage Disk VHDs and attach to Storage Server VM
$VHDPath = $VMPath
$i=0
ForEach ($_ in 1..6)
{
$i++
$DiskName = "Disk0" + $i + ".vhdx"
$VHDFile = "$VHDPath$DiskName"
Write-Verbose "New-VHD - Creating VHDFile [$VHDFile] Size 5GB"
New-VHD -path $VHDFile -Size 5GB -Fixed | Out-Null
Write-Verbose "Add-VMHardDiskDrive - Attaching [$VHDFile] to VM $VMName"
Add-VMHardDiskDrive -VMName $VMName -Path $VHDFile -ControllerType SCSI
}
}
Write-Output "Copying VM Template [$VHDTemplate] to $VMPath$VMName.vhdx"
$Status = Copy-Item $VHDTemplate "$VMPath$VMName.vhdx"
Write-Verbose "Creating VM $VMName"
New-VM -Name $VMName -MemoryStartupBytes 1GB -Generation 2 -VHDPath "$VMPath$VMName.vhdx" -Switchname "Management"
Write-Verbose "Set VM DynamicMemory and ProcessorCount 2"
Set-VM -Name $VMName -DynamicMemory -ProcessorCount 2
Write-Verbose "Set VM for Virtualization Extensions"
Set-VMProcessor -VMName $VMName -ExposeVirtualizationExtensions $true
Write-Verbose "Enable Mac Address Spoofing"
Get-VMNetworkAdapter -VMName $VMName | Set-VMNetworkAdapter -MacAddressSpoofing On
if ($AddStorageDisks)
{
Write-Verbose "Adding Storage Disks to VM"
AddStorageDisks
}
}
}
Create the storage server VMs
Run the following commands below to create your storage server VMs.
Change the VMPath and VHDTemplate parameters for your environment. The commands also assume the path of the PowerShell CmdLet module file is on the current working directory. Update this path if required.
Import-Module -Name .New-vS2DNode
New-vS2DNode -VMName Storage1 -VMPath E:VMsStorage1 -VHDTemplate E:VMsWin2016-Core-TemplateWin2016-Core-Template.vhdx -AddStorageDisks $true -Verbose
New-vS2DNode -VMName Storage2 -VMPath E:VMsStorage2 -VHDTemplate E:VMsWin2016-Core-TemplateWin2016-Core-Template.vhdx -AddStorageDisks $true -Verbose
New-vS2DNode -VMName Storage3 -VMPath E:VMsStorage3 -VHDTemplate E:VMsWin2016-Core-TemplateWin2016-Core-Template.vhdx -AddStorageDisks $true -Verbose
New-vS2DNode -VMName Storage4 -VMPath E:VMsStorage4 -VHDTemplate E:VMsWin2016-Core-TemplateWin2016-Core-Template.vhdx -AddStorageDisks $true -Verbose
Get-vS2DNode
Enter the following command:
Get-vS2DNode -VMName -VMPath -VHDTemplate [-AddStorageDisks $true|$false]
- VMName – The name of the Virtual Machine to create
- VMPath – The path where the new Virtual Machine and attached Virtual Hard Drives will be created
- VHDTemplate – The full path including the file name of the Template VM (created in the instructions above)
- AddStorageDisks – This command will optionally create VHD files associated with the new VM. These VHD disks simulate directly attached hard disks for a storage server. If this parameter is negated, the command will create a standard VM, which can be used for other purposes such as AD servers or Hyper-V compute servers.
Results
With the Storage VMs built and running we can log into one and see the results.

The above storage VM has one operating disk with 20GB and six directly attached virtual SCSI disk drives. When the storage servers are joined into a cluster, the storage cluster will have 24 disk drives available to add to a Storage Spaces pool.
Summary
The Virtual Lab created is now a base infrastructure to build into a complete hybrid cloud environment. The complete hybrid cloud can be constructed by adding roles and configurations, clustering the servers, etc. Each server is compatible with both the Storage Spaces Direct and Hyper-V roles. This provides an environment that supports:
- Windows Failover Clusters
- Hyper-V hosted Windows and Linux Virtual Machines
- Live migrations of VMs
- Containers running (not too heavy) workloads
- Practically any private or hybrid cloud infrastructure
For instructions to configure this environment onto a Hyper-Converged Storage Spaces Direct cluster, refer to Configuring Storage Spaces Direct – Step by Step Part 1 Core Cluster.
Please do provide feedback on errors or any other comments below.

There is no script txt for Get-vS2DNode…..
Was following the guide and got stuck here
Sorry about the broken link. Thanks for reporting it. Fixed!
Hi,
I’m trying to get this to work with Server 2019, but it looks like the module is not compatible, do you have a guide, or are you planning to write one, for newer versions of Windows Server?