Windows Server 2016 TP5

Windows Server 2016 Technical Preview 5 has just been released. Check what’s new in TP5 on this TechNet page

Let’s quickly review the top 10 reasons why you’ll love Windows Server 2016:

There are also some fresh news related to Nano server:

Bonus 1: There’s a free e-book about Windows Server 2016.

Bonus 2:: I’ve updated the demo code I presented last year about How to use WDS to PXE Boot a Nano Server VHD with PowerShell published on PowerShell Magazine

If you use the updated version below, you end up with 2 virtual machines: a Windows Server 2016 TP5 (with Active Directory and WDS) and a Nano VM ready to be provisioned through PXE.

The updated code for TP5 is available as a gist on this page.

Let’s see quickly what’s new:

The Convert-WindowsImage.ps1 script and the NanoServerImageGenerator module are now located on the (ISO):\NanoServer\NanoServerImageGenerator folder.

The New-NanoServerImage function has some new parameters like DeploymentType, Edition,… You can see below a huge comment block that contains a comparison of packages differences between TP4 and TP5 as well as details about syntax differences between TP4 and TP5 version of the New-NanoServerImage function.

A small gotcha. I’ve had to specify the Active Directory module version in the DSC configuration because I had multiple versions installed locally. If you’ve got the most up-to-date version, you’ll have to adjust the version I’ve hardcoded (‘2.8.0.0’ in my case).

One last thing, the code below assumes that you’ve downloaded and stored the TP5 ISO file in a directory named TP5 under your current user’s ‘Downloads’ directory.

if (-not(Get-VMSwitch -SwitchType Internal -ErrorAction SilentlyContinue| Where Name -eq 'Internal-Test' )) {
# Create an internal switch on Hyper-V
($VMswitch = New-VMSwitch -Name "Internal-Test" -SwitchType Internal)
# Set a static IP address on Hyper-V switch
Get-NetAdapter |
Where Name -eq "vEthernet ($($VMswitch.Name))" |
Where InterfaceDescription -match "Hyper-V\sVirtual\sEthernet Adapter" |
New-NetIPAddress -IPAddress 10.0.0.1 -PrefixLength 24
} else {
Write-Information -Msg "Got an internal VM switch named Internal-Test" -InfA 2
Get-NetAdapter |
Where Name -eq "vEthernet (Internal-Test)" |
Where InterfaceDescription -match "Hyper-V\sVirtual\sEthernet Adapter" |
Get-NetIPAddress -AddressFamily IPv4
}
# Set the path to ISO
$iso = $ExecutionContext.SessionState.Path.
GetUnresolvedProviderPathFromPSPath(
'~/downloads/TP5/en_windows_server_2016_technical_preview_5_x64_dvd_8512312.iso'
)
# Integrity check of ISO file
# SHA1: 5D2A2795DCA417ED66DFC6B18D733CE2BD09EC63
if (
(Get-FileHash -Path $ISO -Algorithm SHA256 -ErrorAction SilentlyContinue).Hash -eq
'E74E7400CD852137A778317CFE0A30D1CB5978DF2ECEC02795E863E50A1EDA8A'
){
Write-Information -Msg "Got the correct Technical Preview 5 iso file" -InfA 2
} else {
Write-Warning -Message "Don't have the correct ISO of the Technical Preview 5"
break
}
# Mount ISO
Mount-DiskImage -ImagePath $iso -StorageType ISO -Access ReadOnly -PassThru
$dl = (Get-DiskImage -ImagePath $iso | Get-Volume).DriveLetter
If (Test-Path -Path "$($dl):\NanoServer\NanoServerImageGenerator\NanoServerImageGenerator.psm1") {
Import-Module "$($dl):\NanoServer\NanoServerImageGenerator\NanoServerImageGenerator.psm1" -Verbose -Force
}
# Define VM Name
$VM = "DC1-test"
# Set parent VHD
$ServerVHD = (Join-Path -Path ((Get-VMHost).VirtualHardDiskPath) -ChildPath "$VM.vhd")
# New TP5: dot source the Convert-WindowsImage function
. "$($dl):\NanoServer\NanoServerImageGenerator\Convert-WindowsImage.ps1"
# Create parent VHD
# Convert the WIM file to a VHD using the loaded Convert-WindowsImage function
if (-not(Test-Path -Path $ServerVHD -PathType Leaf)) {
Convert-WindowsImage -Sourcepath "$($dl):\sources\install.wim" `
-DiskLayout BIOS -VHDPath $ServerVHD `
-Edition 2 -Verbose:$true
}
Write-Information -Msg "Created parent VHD: size = $('{0:N2} GB' -f ((Get-item $ServerVHD).Length/1GB))" -InfA 2
# Create child VHD
$cvp = (Join-Path -Path ((Get-VMHost).VirtualHardDiskPath) -ChildPath "$VM-child.vhd")
$childVHD = New-VHD -Path $cvp -ParentPath $ServerVHD -Differencing
# Create a VM Gen 1
New-VM -Name $VM -MemoryStartupBytes 2048MB -NoVHD -SwitchName Internal-Test -Generation 1
# Attach disk
Get-VM $VM | Add-VMHardDiskDrive -Path $childVHD.Path
# Increase processor count for DC
Get-VM $VM | Set-VMProcessor -Count 2
# Mount the VHD
$cm = Mount-VHD -Path $childVHD.Path -Passthru
$cml = (Get-Disk $cm.DiskNumber | Get-Partition | Where DriveLetter | Select -First 1).DriveLetter
# Prepare a Nano VHD with the new script
$bdir = Join-Path (Split-Path $iso -Parent) -ChildPath "Base"
if (-not(Test-Path -Path $bdir -PathType Container)) {
mkdir $bdir
}
$admincred = Get-Credential -Message 'Admin password of your Nano image' -UserName 'Administrator'
if (Test-Path -Path "$bdir\Target") {
Get-Item -Path "$bdir\Target" | Remove-Item -Verbose
}
$nnHT = @{
DeploymentType = 'Guest' ; #NEW TP5: Guest or Host
Edition = 'DataCenter' ; #NEW TP5: Datacenter or Standard
ComputerName = 'Nano-PXE' ;
MediaPath = "$($dl):\" ;
BasePath = $bdir ; # The location for the copy of the source media
TargetPath = "$bdir\Target\Target.vhd" ; # The location of the final, modified image # \.vhdx?$" pattern.
#New TP5 > removed #Language = 'en-US' ; # The language locale of the packages
#New TP5 > removed #GuestDrivers = $true ; # Add the Guest Drivers package (enables integration of Nano Server with Hyper-V when running as a guest).
AdministratorPassword = $admincred.Password ;
}
New-NanoServerImage @nnHT
# notepad "$($env:Temp)\NanoServerImageGenerator.log"
# notepad "$($env:Temp)\NanoServerImageGenerator (DISM).log"
# Comparing packages
<#
Microsoft-OneCore-ReverseForwarders-Package.cab => in TP4
Microsoft-Windows-Server-SCVMM-Compute-Package.cab => in TP4
Microsoft-Windows-Server-SCVMM-Package.cab => in TP4
Microsoft-NanoServer-BootFromWim-Package.cab <= in TP5
Microsoft-NanoServer-Host-Package.cab <= in TP5
Microsoft-NanoServer-SCVMM-Compute-Package.cab <= in TP5
Microsoft-NanoServer-SCVMM-Package.cab <= in TP5
Microsoft-NanoServer-SecureStartup-Package.cab <= in TP5
Microsoft-NanoServer-ShieldedVM-Package.cab <= in TP5
#>
<#
# Compare the syntax of the New-NanoServerImage function
gcm New-NanoServerImage -Syntax
# TP3
New-NanoServerImage [[-MediaPath] <String>] [-BasePath] <String> [-TargetPath] <String> [[-ExistingVHDPath]
<String>] [[-Language] <String>] [-Storage] [-Compute] [-Defender] [-Clustering] [-OEMDrivers] [-GuestDrivers]
[-ReverseForwarders] [[-ExtraPackages] <String[]>] [-ForAzure] [[-ComputerName] <String>] [-AdministratorPassword]
<SecureString> [[-DomainName] <String>] [[-DomainBlobPath] <String>] [-ReuseDomainNode] [[-DriversPath] <String>]
[-EnableIPDisplayOnBoot] [[-DebugMethod] <String>] [-EnableEMS] [[-EMSPort] <Int32>] [[-EMSBaudRate] <Int32>]
[-EnableRemoteManagementPort] [<CommonParameters>]
# TP4
New-NanoServerImage [[-MediaPath] <string>] [[-BasePath] <string>] [-TargetPath] <string> [[-Language] <string>]
[[-MaxSize] <uint64>] [[-Packages] <string[]>] [[-ComputerName] <string>] [-AdministratorPassword] <securestring>
[[-DomainName] <string>] [[-DomainBlobPath] <string>] [[-DriversPath] <string>] [[-InterfaceNameOrIndex] <string>]
[[-Ipv6Address] <string>] [[-Ipv4Address] <string>] [[-Ipv4SubnetMask] <string>] [[-Ipv4Gateway] <string>]
[[-DebugMethod] <string>] [[-EMSPort] <byte>] [[-EMSBaudRate] <uint32>] [[-MergePath] <string>] [-Storage] [-Compute]
[-Defender] [-Clustering] [-OEMDrivers] [-GuestDrivers] [-ReverseForwarders] [-Containers] [-ForAzure]
[-ReuseDomainNode] [-EnableEMS] [-EnableRemoteManagementPort] [<CommonParameters>]
# TP5
New-NanoServerImage [-DeploymentType] <string> [-Edition] <string> -TargetPath <string> -AdministratorPassword <securestring>
[-MediaPath <string>] [-BasePath <string>] [-MaxSize <uint64>] [-Storage] [-Compute] [-Defender] [-Clustering] [-OEMDrivers]
[-Containers] [-Packages <string[]>] [-ServicingPackages <string[]>] [-ComputerName <string>] [-UnattendPath <string>]
[-DomainName <string>] [-DomainBlobPath <string>] [-ReuseDomainNode] [-DriversPath <string>] [-InterfaceNameOrIndex <string>]
[-Ipv6Address <string>] [-Ipv6Dns <string[]>] [-Ipv4Address <string>] [-Ipv4SubnetMask <string>] [-Ipv4Gateway <string>]
[-Ipv4Dns <string[]>] [-DebugMethod <string>] [-EnableEMS] [-EMSPort <byte>] [-EMSBaudRate <uint32>]
[-EnableRemoteManagementPort] [-CopyFiles <string[]>] [-SetupCompleteCommands <string[]>] [-RamdiskBoot] [-Development]
[<CommonParameters>]
#>
# TP3 version:
# New -Defender
# New -ForAzure
# TP4 version:
# Rem -ExistingVHDPath
# Rem -EnableIPDisplayOnBoot
# Rem -ExtraPackages
# New -MaxSize
# New -Packages
# New -Containers
# New -InterfaceNameOrIndex
# New -Ipv6Address
# New -Ipv4Address
# New -Ipv4SubnetMask
# New -Ipv4Gateway
# New -MergePath
# TP5 version:
# New -DeploymentType
# New -Edition
# New -ServicingPackages
# New -UnattendPath
# New -Ipv6Dns
# New -CopyFiles
# New -SetupCompleteCommands
# New -RamdiskBoot
# New -Development
# Rem -Language
# Rem -ReverseForwarders
# Rem -GuestDrivers
# Setupcomplete.cmd file
$s = @'
@echo off
:: Define a static IP for the DC
netsh int ip set address name="Ethernet" source=static address=10.0.0.10/24 gateway=10.0.0.1
:: Configure the DNS client
netsh dns set dnsservers name="Ethernet" source=static address=10.0.0.10 validate=no
'@
mkdir "$($cml):\Windows\Setup\Scripts"
$s | Out-File -FilePath "$($cml):\Windows\Setup\Scripts\setupcomplete.cmd" -Encoding ASCII
# Unattend.xml
$unattendDC1 = @'
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
<settings pass="oobeSystem">
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State&quot; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
<UserAccounts>
<AdministratorPassword>
<PlainText>false</PlainText>
<Value>UABAAHMAcwB3ADAAcgBkAEEAZABtAGkAbgBpAHMAdAByAGEAdABvAHIAUABhAHMAcwB3AG8AcgBkAA==</Value>
</AdministratorPassword>
</UserAccounts>
<RegisteredOwner>Tuva user</RegisteredOwner>
<RegisteredOrganization>NanoRocks</RegisteredOrganization>
<OOBE>
<HideEULAPage>true</HideEULAPage>
</OOBE>
</component>
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State&quot; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
<SystemLocale>en-US</SystemLocale>
<InputLocale>0409:0000040c</InputLocale>
<UILanguage>en-US</UILanguage>
<UserLocale>en-US</UserLocale>
</component>
</settings>
<settings pass="specialize">
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State&quot; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
<ComputerName>DC1-test</ComputerName>
<ProductKey>NB4WH-BBBYV-3MPPC-9RCMV-46XCB</ProductKey>
</component>
<component name="Microsoft-Windows-DNS-Client" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State&quot; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
<DNSSuffixSearchOrder>
<DomainName wcm:action="add" wcm:keyValue="1">10.0.0.10</DomainName>
</DNSSuffixSearchOrder>
</component>
<component name="Microsoft-Windows-UnattendedJoin" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State&quot; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
<Identification>
<JoinWorkgroup>test.local</JoinWorkgroup>
</Identification>
</component>
</settings>
<cpi:offlineImage cpi:source="wim:c:/iso/sources/install.wim#Windows Server 2012 R2 SERVERSTANDARD" xmlns:cpi="urn:schemas-microsoft-com:cpi" />
</unattend>
'@
$unattendDC1 | Out-File -FilePath "$($cml):\Unattend.xml" -Encoding UTF8
# Get required DSC resource
if (-not (Get-Module -ListAvailable -Name xActiveDirectory)) {
Find-Module -Name xActiveDirectory -Repository PSGallery | Install-Module -Verbose
}
# Define environment
$ConfigData = @{
AllNodes = @(
@{
NodeName = 'localhost';
PSDscAllowPlainTextPassword = $true;
PSDscAllowDomainUser = $true ;
RequiredFeatures = @(
@{ Name = 'DHCP'}
@{ Name = 'DNS'}
@{ Name = 'WDS'}
@{ Name = 'RSAT-DHCP'}
@{ Name = 'RSAT-DNS-Server'}
@{ Name = 'WDS-AdminPack'}
)
DCAdminPassword = New-Object pscredential -ArgumentList 'nanorocks\administrator',
(ConvertTo-SecureString -String 'P@ssw0rd' -Force -AsPlainText)
SafeAdminPassword = New-Object pscredential -ArgumentList 'Password Only',
(ConvertTo-SecureString -String 'Azerty@123' -Force -AsPlainText)
}
)
}
# DSC config
Configuration DCConfig {
Param()
# Import-DscResource -ModuleName xActiveDirectory
# Specify a version if you've multiple ones installed locally
Import-DscResource -ModuleName xActiveDirectory -ModuleVersion '2.8.0.0'
Import-DscResource –ModuleName 'PSDesiredStateConfiguration'
Node localhost {
LocalConfigurationManager {
RebootNodeIfNeeded = $true;
}
WindowsFeature ADDS {
Name = 'AD-Domain-Services';
Ensure = 'Present';
}
foreach ($f in $Node.RequiredFeatures)
{
WindowsFeature $f.Name
{
Name = $f.Name ;
Ensure = 'Present';
}
}
xADDomain DSDC1 {
DomainName = 'nanorocks.local';
DomainAdministratorCredential = $Node.DCAdminPassword
SafemodeAdministratorPassword = $Node.SafeAdminPassword
DependsOn = '[WindowsFeature]ADDS';
}
}
}
# Compile config into MOF file
if (-not(Test-Path -Path ~/Documents/DSC) ){ mkdir ~/Documents/DSC }
DCConfig -outputPath ~/Documents/DSC -ConfigurationData $ConfigData
# Copy DSC resource
$cHT = @{
Path = 'C:\Program Files\WindowsPowerShell\Modules\xActiveDirectory';
Destination = "$($cml):\Program Files\WindowsPowerShell\Modules\xActiveDirectory"
}
Copy-Item @cHT -Recurse -Force
# Copy DSC config
Copy-Item -Path ~/documents/DSC/*.mof -Destination "$($cml):\Users\Public\Documents"
# Copy original boot image from ISO
Copy-Item -Path "$($dl):\Sources\boot.wim" -Destination "$($cml):\Users\Public\Documents"
# Copy prepared Nano.vhd
Copy-Item -Path "$bdir\Target\*.VHD" -Destination "$($cml):\Users\Public\Documents"
# dir "$($cml):\Users\Public\Documents"
# Unmount ISO file
Get-DiskImage -ImagePath $iso | Dismount-DiskImage
# Unmount VHD
Dismount-VHD -Path $childVHD.Path
Start-Vm -VMName $vm
# DCPromo over PowerShell Direct
Invoke-Command -VMName $VM -Credential (Get-Credential 'test.local\administrator') -ScriptBlock {
Set-DscLocalConfigurationManager C:\Users\Public\Documents
Start-DscConfiguration C:\Users\Public\Documents -Verbose -Wait
exit
}
# Post-install
Invoke-Command -VMName $VM -Credential (Get-Credential 'nanorocks\administrator') -ScriptBlock {
# DHCP configuration
# Authorize
if (-not(Get-DhcpServerInDC | Where DnsName -eq "$($env:computername).$($env:USERDNSDOMAIN)")) {
Add-DhcpServerInDC
} else {
Get-DhcpServerInDC
}
# Scope
Add-DhcpServerv4Scope -StartRange 10.0.0.20 -EndRange 10.0.0.100 -Name "Nano scope" -State Active -SubnetMask 255.255.255.0
# Activate: done with add-dhcpserverv4scope -state param
# WDS
mkdir C:\RemoteInstall
wdsutil /verbose /progress /initialize-server /RemInst:c:\RemoteInstall # /Authorize
wdsutil /start-server
wdsutil /verbose /progress /set-server /AnswerClients:ALL
Import-WdsBootImage -Path C:\Users\Public\Documents\boot.wim
dir C:\Users\Public\Documents\*.vhd | Import-WdsInstallImage
}
# Create test VM Generation 1 and add legacy network card for PXE boot
$testVM = 'Nano-test-pxe'
New-VHD -Path (Join-Path -Path ((Get-VMHost).VirtualHardDiskPath) -ChildPath "$($testVM).vhdx") -Dynamic -SizeBytes 127GB
New-VM -VMName $testVM -Generation 1 -MemoryStartupBytes 1024MB -NoVHD -SwitchName Internal-test |
Remove-VMNetworkAdapter
Get-VM -VMName $testVM |
Add-VMNetworkAdapter -IsLegacy:$true -SwitchName 'Internal-test'
Get-VM -VMName $testVM |
Add-VMHardDiskDrive -Path (Join-Path -Path ((Get-VMHost).VirtualHardDiskPath) -ChildPath "$($testVM).vhdx")
Start-VM -VMName $testVM

2 thoughts on “Windows Server 2016 TP5

  1. TP 5 didn’t work with us. I couldn’t join clients to domains. Just going back to TP4. Hope release candidate is more admin friendly

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.