This the fifth part in a multi-part set of articles on building a test lab with Hyper-V and PowerShell. See the following prior articles in this series.
- The purpose of these scripts/articles
- Creating a reference VHDX
- Creating Virtual Machines and the related differencing VHDXs
- Creating a new forest and new domain controller .
Configuring the First DC
In the last article, I showed you how to create a domain controller in a new forest by taking a newly installed workgroup server and promoting it to be the first domain controller in a new domain/forest. Since the DC provides the AD environment for the rest of the VMs in my test lab(s), it has to become the DC before any other VMs are created. Once the server becomes the domain controller, a second script is used to configure the DC. Note that most of the other servers can be configured in just one step (although the jury’s still out that with respect to Lync and Exchange).
In this article I present a second configuration script for the domain controller, snappily named Configure-DC1-2.ps1. This second script just finishes off the configuration and setup of the DC. Once the DC1 VM has been created and promoted to being a domain controller, you use this second script to finish configuration.
From a work flow perspective, once the DC has been created, creating and configuring other new VMs can be done in parallel with configuring DC1 (i.e. running Configure-DC1-2). Also, if you are creating VMs that rely on DHCP, you would need to complete the DCHP configuration before those VMs are created.
In my lab’s case, configuration the first domain controller, DC1, is pretty simple:
- Set the VM to automatically logon as the domain admin – in lab environments, life really is too short to have to type credentials any more than is absolutely needed. So I set the registry settings to enable auto admin logon
- Install Key Windows features - I include some simple features, including IIS (which is needed to enable the DC to be a CA).
- Install and configure basic DHCP - Most of my lab machines have fixed IP addresses, but having a small DHCP block seems a good thing! I allocate 20 IP addresses, but you could change that as needed. I also configure this scope with some basic options (IP, subnet mask, and DNS Server). You could add a default gateway if you want to enable routing via the host.
- Create a second administrator – I create one extra user, me (TFL), and add this user to domain and enterprise admin groups. I have a further script Configure-ReskitAD.ps1, as part of this series, that adds a richer AD environment in terms of a coupe of OUs, and more users.
Once that has been done, I do two more things in the script (outside the configuration block):
- Force a reboot of the VM – The very last thing the script block does before returning is to call restart-computer. The reboot is, in effect, asynchronous. Thus after the script exits and control is passed to the main script running on the Hyper-V box which continues while the DC reboots. After the exit, the script restarts DC1.
- Take a snapshot of the DC. This is useful if I want to do some AD configuration but then back out of that. To cater for the async nature of the reboot (it happens in another process/VM), I use the the parameters ‘–Wait –For PowerShell’ which waits till the system has rebooted, the user has logged on before proceeding to take the actual snapshot. .
Using Remoting to Configure DC1
In the first two scripts that create and start up the VM, the scripts contain a function definition that is then run against the local system, i.e. the host you are using to run Hyper-V. In my case, this was done on Windows 8 on my laptop and one of my Server 2012 boxes. They both run Hyper-V well so testing is easy both at home and on the road. As I noted previously, the remainder of the scripts I use that to setup and configure the domain and servers use remoting. The following pattern if these scripts is as follows:
- Create a script block, $CONF or similar, containing PowerShell code to perform some configuration on a server. The PowerShell code is intended to run in the target VM.
- Use Invoke-Command, and the appropriate credentials, to run that script block on a remote server (i.e. one of the Hyper-V VMs you are building/configuring.
This process is flexible and allows me to do things before invoking the script block. For example, to install SQL, Exchange or Lync, I need to have the product CD inserted in the D: drive. For Exchange, I have to load some pre-requisites onto the server, for example bits of IIS, etc. that are not needed for other labs. SO in that case, the configuration script file can create a couple of script blocks to divide up the work. In the longer term I consolidate the multiple script blocks, but that’s work to be done!
These scripts were designed to support me in writing and developing courseware. Since the development work can be error-prone plus with a need to test, test, and re-test lab instructions, I need to take snapshots before and after key configuration events. So what this script does, at the very end, is to take a VM snapshot and label it as being created by this script. You can, of course, comment out this if you don’t need to have a snapshot!
Using the Scripts
When I am building out a new set of VMs, I open ALL these scripts in the ISE on the Hyper-V host. Whilst I am at home, that means running these via a terminal services window against one of my Hyper-V servers or my laptop. Once I have all the scripts open, I just work through them, tweaking the unattend.xml, building the base disk, building then promoting DC1, finishing off DC1 configuration, configuring a CA, configuring the IIS servers, etc.
Getting the Scripts
I have published the full set of deployment scripts to my web site, at http://www.reskit.net/powershell/vmbuild.zip. Note that some of the scripts in this zip file are very much works in progress that are changing, and hopefully improving, as I publish these articles. I reserve the right to change any of all of them from time to time. I will try to blog any important changes.
I am also publishing the individual scripts over on my PowerShell Scripts Blog:
Recent Script Changes
Since starting this series, I’ve been tidying up the scripts. In some cases, I’ve moved parameters into hash tables to increase readability. The changes to the scripts are now added to the script itself. One key change is that I set Auto-Admin logon for all servers, and force a reboot of the server after configuring it. I’ve also added some judicious Hyper-V check pointing into some of the scripts to simplify both further testing and to suit my courses.
In the original post, the reboot and snapshot were not handled in a tidy fashion. I re-coded this logic so that the configuration script block does NOT do the restart. Instead, I let the script block continue, and exit back to the main Configure-DC1-2 script block where I then forcibly reboot the DC, wait till the reboot has completed then take the snapshot. Just a little more elegant and it ensures that the snapshot after the reboot has completed and the auto-admin logon has occurred. This makes reverting back to the snapshot that bit easier.
The next couple of scripts, which I hope to get documented this week, including building and configuring general purpose servers and creating a Certificate Authority. I also have some utility scripts that I have added and will also be documenting.
Any comments? I’d love to hear from you – either as comments to this blog post, or via email.