Lab-Ops part 12 – A crude but effective Domain Controller

I realised I need to recreate a Domain Controller in my labs and in so doing I noticed a snag in my earlier scripts that really breaks when I use the same snippet for a new DC.  I have this test to see if a VM is ready to be used..

do {Start-sleep –seconds 10}

until(Get-VMIntegrationService $VMName | where name -eq "Heartbeat").PrimaryStatusDescription -eq "OK")

#the code to create the $localcred credential is at the end of this post

It does work in that this will return true if the VM is on, but if a VM is coming out of sysprep this do until loop will exit way before I can log in and actually use the VM. So then I tried this command in my until clause ..

Invoke-Command –command 192.168.10.1 {dir c:\} –ErrorAction SilentlyContinue –Credential $LocalCred

a crude but effective test based on whether I could connect to and run a simple command on the VM.That worked for most of my VMs, but this was still no good for my script to build a Domain Controller (DC). The problem here is that after I add in the feature (which doesn’t require a reboot)..

Install-WindowsFeature -name AD-Domain-Services –IncludeManagementTools

and then create the Domain with..

Install-ADDSForest –DomainName Contoso.com –safemodeadministratorpassword (cofor thisnverttosecurestring “Passw0rd” –asplaintext –force) –force

this will at some point cause a reboot but this doesn’t happen inline as this command is itself calling  PowerShell in a session I can’t control.  The result is that my script will continue to execute while this is going on in the background. So my test for a C Drive could work before the reboot and I would be in a mess because some subsequent commands would fail while my VM reboots. So my hack for this is to trap the time my VM takes to come out of sysprep..

$Uptime = (Get-VM –Name $VMName).uptime.totalseconds

and test when the current uptime is LESS than $Uptime which can only be true after the VM has rebooted.

do {Start-sleep –seconds 10}

until(Get-VM –Name $VMName).uptime.totalseconds –lt $Uptime)

Then I can test to see if the VM is ready to be configured by checking the Active Directory Web Service is alive on my new DC..

Get-Service –Name ADWS | where status –EQ running

However even after this test returned true I was still getting errors from PowerShell saying that a default domain controller couldn't be found so I specified the DC with a –server switch in each command for example ..

New-ADOrganizationalUnit -Description:"RDS VDI Collection VMs" -Name:"RDS-VDI" -Path:"DC=Contoso,DC=com" -ProtectedFromAccidentalDeletion:$true -Server:"RDS-DC.Contoso.com"
  Just to be extra sure I also slapped in a 20 second wait to ensure the service really was there as I want this to run cleanly again and again.

I won’t bore you with the code for adding the rest of the users, groups etc. to Active Directory as the easiest way to write that is to do something to a Domain controller in the Active Directory Administrative Centre and grab the stuff you need from the PowerShell History at the bottom of the console..

image

I also showed you how to read and write to text based CSV files in part 5 of this Lab Ops Series so you could amend my script to have a whole list of objects to add in to your DC from a CSV file that you have previously lifted from a production DC.

I also need a DHCP server in my lab and I typically put that as a role on MY DC.  Here again you can see how PowerShell has improved for newbies like me..

#Install the DHCP Role
Add-WindowsFeature -Name "DHCP" -IncludeManagementTools -IncludeAllSubFeature
#Authorize this DHCP server in AD
Add-DhcpServerInDC -DnsName contoso.com
#Setup a scope for use with RDS/VDI later on
Add-DhcpServerv4Scope -StartRange 192.168.10.200 -EndRange 192.168.10.254 -SubnetMask 255.255.255.0 -Name RDSDesktops -Description "Pool for RDS desktop virtual machines"
#Set up the DNS Server Option (6) in DHCP so DHCP clients have the DNS Server entry set
Set-DhcpServerv4OptionValue -OptionId 6 -value 192.168.10.1
Set-DhcpServerv4OptionValue -OptionId 15 -value "contoso.com"

Sadly the trusty old DHCP MMC snapin doesn’t have a history window so I looked at the options set by the wizard and set them as you can see here.  Once all this is working I can go on to create the other VMs in this series. However this DC also sets up and uses a Hyper-V Internal Virtual Switch “RDS-Switch” and ensures that my physical host (Orange – which is my big Dell laptop) can connect to my new DC on that switch..

# Setup the Networking we need - we'll use an internal network called RDS-Switch. If it's not there already create it and set DNS to point to our new DC (RDS_DC) on 192.168.10.1
If (!(Get-VMSwitch | where name -EQ $VMSwitch )){New-VMSwitch -Name $VMSwitch -SwitchType Internal}
# Now configure switch on the host with a static IPaddress and point it to our new VM for DNS
$NetAdapter = Get-NetAdapter | Where name -Like ("*" + $VMSwitch + "*")

#Note the use of the !(some condition) syntax to refer to not true
If (!(get-NetIPAddress -InterfaceAlias $NetAdapter.InterfaceAlias -IPAddress "192.168.10.100" -PrefixLength 24)) {New-NetIPAddress -InterfaceAlias $NetAdapter.InterfaceAlias -IPAddress "192.168.10.100" -PrefixLength 24}
Set-DnsClientServerAddress -InterfaceAlias $NetAdapter.InterfaceAlias -ServerAddresses "192.168.10.1"

The final piece of the puzzle is to join my physical laptop  to this domain,   as I am going to need the host for VDI, and for now I am going to run that manually with the add computer command..

$LocalCred = new-object -typename System.Management.Automation.PSCredential -argumentlist "orange\administrator", (ConvertTo-SecureString "Passw0rd" -AsPlainText -Force )
$DomainCred = new-object -typename System.Management.Automation.PSCredential -argumentlist "Contoso\administrator", (ConvertTo-SecureString "Passw0rd" -AsPlainText –Force )
add-Computer ComputerName Orange –Domain Contoso.com–LocalCredential $Localcred –DomainCredential $DomainCred –Force

Start-Sleep –seconds 5

Restart-Computer Orange $localcred

..and of course to test that I need to pull it out of that domain before I test it again with Remove-Computer. By the Way don’t put the –restart switch on the end of add computer as that will bounce your Host and hence your DC as well and while your host appears to be domain joined it doesn’t show up in the domain.

I have posted the whole script on SkyDrive (Create RDS-DC.ps1) and it’s called RDS-DC as it’s designed to underpin my Remote Desktop Services demos. For example there are a couple of write-host lines in there to echo output to the console where in reality you would log progress to a file.

As ever any advice and comments on this is welcome and I can repay in swag and by properly crediting your work.