Showing posts with label Deployment Scripts. Show all posts
Showing posts with label Deployment Scripts. Show all posts

Wednesday, January 23, 2013

Building A Hyper-V Test Lab on Windows 8 – Part 4 Creating a DC

Introduction

This the fourth 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.

Creating the DC

The starting point for creating a DC is having a simple work group VM created and run. In the last article I covered how to build a Hyper-VM Based a differencing/parent pair of disks. That process generates a work group computer, with a known IP address, a known hostname and a known user id/password set of credentials. The VM that is created has just the standard set of services and features that the base installation process generates (i.e. the same as if you just click next/next/next installing a VM from a DVD).

In Windows Server 2012, the process of creating a DC has changed quite considerably from earlier versions of Windows Server. DCPromo.exe is no more – you now promote a server by using PowerShell cmdlets (although I suppose you could use the GUI – but where’s the fun in that?). 

The installation process for a new DC in a new forest comprises two simple steps:

1. Using Install-WindowsFeature to add the AD-Domain-Services and related management tools.

2. Using Install-ADDSForest, create a new domain and domain controller, install DNS, and set the domain/forest modes (i.e. what DCPromo.exe used to do in years gone past).

Using remoting to perform the DC promotion

In the first two scripts that create and start up the VM, I created a function that I then ran on the local system, i.e. the host you are using to run Hyper-V. All the development was done using Windows 8 and Server 2012 which both run Hyper-V. The remainder of the scripts to setup and configure the domain and servers is done using remoting plus some local hyper-v stuff. Basically, the remaining scripts all have the following pattern:

a) Create a script block containing PowerShell code to perform some configuration on a server.

b) Use Invoke-Command to run that script block on a remote server (i.e. one or more 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 and 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. In that case, my published script file can create a couple of script blocks to divide up the work.

When I am building out a new set of VMs, I open ALL the scripts in the ISE on the Hyper-V host (which in most cases is actually being used via a terminal services window!) With all the scripts up, I just work through them, building the base disk, building then promoting DC1, finishing off DC1 configuration, configuring a CA, Configuring the IIS servers, etc.

Promoting with PowerShell

The PowerShell code to carry out the promotion is as follows:

Install-WindowsFeature –Name AD-Domain-Services –IncludeManagementTools
$PasswordSS = ConvertTo-SecureString  -string 'Pa$$w0rd' -AsPlainText -Force
Install-ADDSForest -DomainName Reskit.Org –Force –InstallDNS `
  -
SafeModeAdministratorPassword $PasswordSS  -DomainMode Win2012 `
  -ForestMode Win2012

The first step involves windows loading the necessary components to enable the host to be configured into some sort of DC as well as all the management tools. The second step involved creating a new domain in a new forest. In my case, I set both the forest and domain into Win2012 mode (why not?) as well as specifying a safe mode password.

Completing the DC Promotion

After running these few lines of PowerShell, the Install-ADDSForest cmdlet reboots the machine. At which point, assuming nothing hairy has gone on, you now have a DC. It has one main user, Administrator, whose password is the same as the local machine’s Administrator password (in my case Pa$$w0rd).

Unfortunately, for scripting purposes, the reboot is an asynchronous event – there’s no easy way for a PowerShell script to wait for the reboot and continue. Sure – you can use work flows for that, but I don’t (well not yet!). So to finish off the process of configuring the DC, I’ve created a couple more scripts. The first of these, which I’ll describe later, is one you run after the DC has rebooted. This second script does a bit more configuration on the DC, including adding any users, OUs, computers, etc. that might be needed. The second, at least in my case, is adding a Certificate Authority to the DC. I’ll look at both of these scripts in future articles.

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 still works in progress. 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:

Monday, January 21, 2013

Building A Hyper-V Test Lab on Windows 8 – Part 3 Creating VMs

This the third part in a multi-part set of articles. See the first article for the start of the set and to understand better what this is all about – see here: http://www.tfl09.blogspot.co.uk/2013/01/building-hyper-v-test-lab-on-windows-8.html. And to see the prior article on creating a reference VHDX see here: http://www.tfl09.blogspot.co.uk/2013/01/building-hyper-v-test-lab-on-windows.html.
 
Building a VM
The overall purpose of my VM Build scripts is to create and configure a set of VMs in a test environment. In the last article, I showed how you can create a base or reference disk. In this article, I show how you can take that base disk and create both a differencing disk and a VM that uses that new disk.
 
Each VM created gets a customised Unattend.XML file, which is stored on the differencing disk, once that disk is created. Thus, when the VM is started, OS installation is completed using the XML file. This allows me to do some simple things, like kill the firewall, set the right language(s), etc.  Creating this file was one of my early stumbling blocks!
 
Unattend.XML
From the earliest days of Windows NT, you could create an Unattend.txt file, put it on a floppy disk, insert the floppy into your system then install the OS from the CD. That enabled Windows NT setup to get the details of the installation coming from the Unattend.Txt. I did a lot of that in then NT 3.5/3.51/4.0 days. But with Vista, Microsoft shipped a totally new setup method, with WIM files and with Unattend.txt replaced with (a more complex) Unattend.XML. Pretty much everything I knew about unattend.txt files goes out the window.
 
A key objective I had in creating these build scripts was to avoid having to know too much about these XML files. I got a ‘starter’ copy form my good pals at Lab Center in Stockholm and have tweaked it (removing things I don’t need) and creating useful default settings for things (e.g. keyboard).
 
I really wanted to avoid becoming a deployment wizard and use a generic Unattend.XML file. But sadly, that objective proved to be a little unreasonable, but I’ve tired hard to minimise the number of things configured in the XML file and do as much as I can via PowerShell scripts after the OS has been installed.
 
Using Unattend.XML files is pretty simple, as long as you understand both the Windows build model and the components you can add to windows. To use the Unattend.XMO file, you create/configure the XML file, save it on the differencing disk and add the differencing disk to the VM. This way, the unattend.XML file guides Windows Setup to create the VM as you need it.  Subsequent scripts that configure the VM further (e.g. adding application specific windows component, adding applications and features, etc.).
 
In the Unattend.XML file, I currently specify 14 components in three passes as follows
 

Pass

Component

The effect of this component

Generalize Microsoft-Windows-Shell-Setup Specifies that Sysprep should not remove any icons from the Quick Launch toolbar
Specialize Microsoft-Windows-UnattendedJoin Specifies the domain to join and credentials needed to join or whether to just ‘join’ a named workgroup
  Microsoft-Windows-Shell-Setup Specifies Computer name, registered organsiation and owner, and time zone
  Microsoft-Windows-IE-InternetExplorer Sets home page to blank and whether to disable the run-once wizard
  Microsoft-Windows-Deployment Enables local administrator account
  Microsoft-Windows-International-Core Specifies Input Locale, System Locale, UI Language and UserLocale. The input locale sets an initial keyboard layout.
  Microsoft-Windows-TapiSetup Tapi settings
  Microsoft-Windows-IE-ESC Turns off the IE security settings
  Microsoft-Windows-TerminalServices-LocalSessionManager Enables Terminal services connection to the VM
  Networking-MPSSVC-Svc Turns the firewall off on the VM
  Microsoft-Windows-TCPIP Sets TCP/IP settings, including IP address, subnet mask and default gateway
  Microsoft-Windows-DNS-Client Specifies the DNS Server IP address
OobeSystem Microsoft-Windows-Shell-Setup Specifies local administrator password, whether to hide the EULA pages plus sets the time zone
  Microsoft-Windows-International-Core Specifies a 2nd language to be setup for this VM
 
The Create-VM function
The core aspects of the VM creation is done with the Create-VM function. The function takes parameters including the VM name, the path to store the VM information for Hyper-V, the path to the reference disk, what network to use, how much memory to set, which Unattend.XML file to use and the IP address, subnet mask and DNS Server Address.
 
The details of the VM created is determined by what is in the Create-VM function, details in the the Unattend.XML file and some details set by the call to the create-VM function. For example, the keyboard settings used are set in the XML file only, whereas the use of dynamic memory is set only in the Create-VM function. The IP address, on the other hand, has a default set  in the XML (10.0.0.250/24). The Create-VM function, however, overwrites this address with the IP address/subnet mask specified  in the call to Create-VM.  The parameters specified on the call to Create-VM are used to update the Unattend.XML file stored on the differencing disk and used to install the OS.
 
I use two XML files – one is used to create a stand alone server the other to create a domain joined server. I use the former to create DC1 and once DC1 has been promoted to be a DC, the later XML file is used to create servers that are domain joined. Both XML files, on the other hand, set keyboard layout
 
This approach of setting some installation options in the XML and others via the function (and resulting in updated XML) seemed to be a good compromise. I only implement parameters to Create-VM that need to be differ3ent in different VMs, whereas installation options
 
Creating the VM
The task of creating/building the VM is performed by the Create-VM function and involves the following steps:
  1. Creating a differencing disk – this is the ‘difference’ between a reference or parent Vhdx  and  the disk. 
  2. Creating a VM in Hyper-V.
  3. Adding the differencing disk into the VM.
  4. Mounting the VHD on the host computer.
  5. Based on a pre-built Unattend.XML, creating a customised Unattend.XML file and saving it to the on the mounted VHDX.
  6. Dismounting the VHDX from the host
  7. Setting VM settings including memory, startup actions etc.
  8. Starting the VM.

Once the VM has started, windows setup proceeds to install Windows as per the Unattend.XML file. The creation of the VM itself takes just 20-30 seconds, followed by the actual installation which takes 10-15 more minutes (and more if you are doing multiple installations in parallel).

The Created VM
The VM created by the Create-VM function will either be a workgroup VM or a VM that has been joined to the domain, as specified in the Unattend.XML file. This VM will be fairly vanilla with only a few options specified (as noted above). There are no extra applications loaded, and the Unattend.dj.xml file only ‘works’ once you have the DC up and running.

The Create-VM script takes around 27-30 seconds to create and start the VM in Hyper-V. On my WIn8 laptop, it take a further 5 minutes to complete the creating of the first DC.

Example
Once you have the reference disk, you can call the Build-VM function like this:

$ref    = …   # Path to the reference disk
$Path   = …   # Path to where to put the VM and differencing disk
$unadj  = …   # Path to Unattend.XML
#     Now Create the VM
Create-VM -Name "Srv1"  -VmPath $Path –ReferenceVHD $Ref  -Network "Internal" `
          -UnattendXML $unadj -Verbose -IPAddr '10.0.0.30/24' `
          -DNSSvr 10.0.0.10  -VMMemory 512mb

You run this script ON the Hyper-V server. Once the Create-VM function completes, which takes between 20-25 seconds in my case, Hyper-V starts up the VM and completes the installation of the OS inside the VM. The complete installation takes 20 minutes or so (depending on your system, how much RAM you give the VM, the speed of your system, etc.). Once the setup is complete, you can move on and configure the VM with application and application settings.

Where are we on this journey?
In the these first three blog posts, I’ve set out the objectives of a VM Build module for building VMs and the two core functions/scripts. The two scripts create a base VM disk, a differencing disk and a VM. Each VM is customised a little in the call to Create-VM – in effect creating a base VM. Once this VM has been created, you can then load additional applications and Windows features (e.g. making the DC a certificate authority). In the next episodes of this set of blog articles, I’ll start looking at the scripts that add those applications and features. And I’ll share the interesting things I’ve discovered along the way. I’ll also publish the scripts and the unattended XML files.

 

 

 

 
Technorati Tags: ,,

Wednesday, January 16, 2013

Building A Hyper-V Test Lab on Windows 8–Part 2 Creating a Reference VHDX

This the second part in a multi-part set of articles. See the first article for the start of the set and to understand better what this is all about – see here: http://www.tfl09.blogspot.co.uk/2013/01/building-hyper-v-test-lab-on-windows-8.html.
Base/Parent Disks in Hyper-V
With Hyper-V, you assign one or more virtual disks to a VM. One trick, borrowed from VMware, is the ability to create parent and differencing disks. The parent disk is a normal VHDX drive built out to a certain point. This can be a completed installation, or a partial installation. The differencing disk is then the difference between the base or parent virtual disk and the contents of the combined virtual disk at some later point in time i.e. after installation. Thus if the base disk was the uninstalled image, the differencing disk would only hold the changed made since installation.
 
On my Windows 8 box, the reference disk is 8.2GB while each of the differencing disk are between 2-3 GB.  In all the 4 VMs currently in a configuration I am testing takes up around 23 GB. Were I to create a full separate drive for each VM, I’d need nearer to 40 GB, so the space reduction is useful!
The way I use this in my labs is simple. I create a base disk which contains the uninstalled image of Windows server using the Create-ReferenceVHDX script. Then I use that reference disk in the Create-VM function that actually creates and starts a VM.
Creating a Reference VHDX using PowerShell
Creating the reference VHDX is pretty simple. The Create-ReferenceVHDX.PS1 script file creates a function, Create-ReferenceVHDX, then at the bottom invokes that function to actually create a reference VHDX. In my testing, it takes around 8 minutes to create the reference disk, most of which is taken up by DISM.EXE applying the relevant image to the base disk.

The creation process is as follows:
  1. First, we load the DISM module.
  2. Next we mount the ISO image used as the basis for the VHDX into the host machine (I.e. the Hyper-V host). The name of the VHDX is passed as a parameter to Create-ReferenceVHDX. We have to get the volume object to then get the drive letter where the IOS is mounted.
  3. We read the install.wim from the appropriate spot on the DVD and get the user to specify which installation contained in the WIM is to be used as the basis for the base disk. I use Out-GridVIew for this, but you could I suppose just take whatever the last option is (or the first) as needed.
  4. The function then creates a new VHDX file to hold this image, which is then initialised. Sometimes this throws up a dialog box but that can be safely ignored.
  5. DISM.exe then runs which applies the chosen install image onto the VHDX. This is quite a long process and can take 10 minutes.
  6. Once the image is laid down, BDCBoot ensures the disk can be booted from.
  7. Finally, the VHDX is dismounted form the local host and the function finished.

See the script for the details of how these steps are carried out!


Using the Create-ReferenceVHDX Function
Using the reference VHDX is pretty simple – three lines in all:

$Iso          = …    # Path to Server 2012 DVD    
$Refvhdxpath  = …    # Path to where the reference VDHX is to go
Create-ReferenceVHDX -Iso $iso -RefVHDXPath $RefVHDXPath  -Verbose

Using the Reference VHDX
Once the reference VHDX is created, you can use it as the basis for creating differencing disks you can then insert into VMs. See Part 3 of this tutorial to see how to do that.

Getting the scripts
The scripts are all published to a zip file: http://www.reskit.net/powershell/vmbuild.zip. Use carefully and enjoy!

Sunday, January 13, 2013

Building a Hyper-V Test Lab on Windows 8 – Part 1

This is the first part of a multi-part blog article on a set of scripts to create VMs using Microsoft’s Hyper-V on both Windows 8 and Server 2012.

Note: this page is being updated along with others in this set as I slowly get all this documented and published.

Background

For many years, I’ve used virtual machines heavily. The articles, courses and books I write rely on VMs for their content. I’ve lost count of the number of domains I’ve built, re-built, broken, fixed over the years. 

The only downside is that I was regularly building and re-building the systems by doing creating a new VM and installing the OS from scratch. This was slow and tedious as well as somewhat error prone.

What I needed was a good, reliable system of creating sets of VMs and configuring them. The base set of services I want to be able to install and use was not that long: the OS (with AD, ADCS, DHCP, DNS, File Services), SQL, and Exchange.

Now that I have these scripts working, or nearly so, I am amazed at how much easier it is to create a set of VMs for particular purpose (e.g. write an article, create a class, build a demo for a talk). I am also finding others that have similar needs. I hope others find these scripts useful!

Building VMs Using Scripts

In the autumn of 2012, I, along with super-star MVP colleague Niklas Goude, started running PowerShell Geek Weeks in Stockholm. A lot of fun – 5 days of going as deep as we can with PowerShell. A key part of the Geek Week adventure is for the delegates to build their own environment AND to be able to take away the tools to re-create this environment at home.

I spent quite some time building some basic scripts – and encountered a lot of dead ends along the way. The first time out was a limited success – limited in that some pieces did not fit together well but a success in that it taught a lot of cool PowerShell features and showed us where we needed to do more. It also helped me to refine the real objectives the tools had to meet. Thanks goes to Mikael Nystrom for helping me with a good starting Unattend.XML!

Objectives of the VM Build module

My main objectives of these build tools were:

1. To enable someone with fairly limited PowerShell skills (or greater!) to use the the scripts simply and flexibly in the classroom and later.

2. To enable building out of a small farm of up to say half a dozen servers with minimal effort.

3. To enable extensibility, in that one could add more scripts to refine the configuration (e.g. adding a script to implement a failover DHCP).

4. To encode things like domain/forest names, user ids, passwords and IP address information to a given standard but make it not too difficult to change that.

5. To avoid the user having to use too much of the new automated setup approach.

6. To keep the use of disk space to a minimum.

The Architecture

The basic architecture of what I am trying to build is shown here:

image

 

The idea is simple – a single reference, parent, disk with a number of separate VMs based on differencing disks. This approach hits objective 6, and enables a simple solution to objective 4.

The Scripts

The key scripts here are as follows:

  1. Create-ReferenceVHDX – this script creates a parent VHDX based on an image from the Install.WIM from a Server (or client) installation DVD.
  2. Create-VM – this script creates a differencing VHDX, based on the reference VHDX, and creates an updated Unattend.xml file, stores this on the differencing drive. The script then starts the VM which then installs Windows onto the differencing disk. You run this script to create the VMs and VHDXs for DC1, Exch1, SQL1, SRV1, SRV2.
  3. Configure-DC1-1 – this script turns the first VM, DC1, into a domain controller in a new forest.
  4. Configure-DC1-2 – this script configures DC1, post installation as a DC. This includes adding and configuring DHCP and creating some users in AD.
  5. Configure –DC1-CA – this script convers DC1 into an Enterprise Root CA, and creates a web responder, complete with SSL support for the /Certsrv application.
  6. Configure-Exch1 – this script configures the Exch1 VM, including installing Exchange 2008 on the Exch1 VM.
  7. Configure SQL1-1 – this script configures the SQL server VM, including installing SQL server itself.
  8. Configure-SRV1-1 - Configure-SRV2-1, these scripts create a pair of application servers, including adding all of the RSAT tools and IIS.
  9. Utility Scripts – these include Set-DVDDriveOnAll (sets a particular DVD/ISO to be in the DVD drive of all VMs), Set-LanguageOnAll – sets the administrator logon have a particular kb layout for all vms, Set-NetFrameworkCoreOnAll (adds the base .NET onto all systems – which is needed for PowerShell V2).

These scripts are now online and you can get them from http://www.reskit.net/powershell/vmbuild.zip.

 

What’s Next?

There are several next steps:

  1. I’ll publish each script both to the PowerShell scripts blog (http://pshscripts.blogspot.co.uk) as well as publishing details of each scripts here. IN publishing the details here, I’ll explain what each script is doing and why I did it that way. As ever, comments are welcome – and may cause further updates to the script set!
  2. I’ll update this page with pointers and anything updated as I complete this set of posts.
  3. Package these scripts up as a downloadable module. Right now, these are just a bunch of scripts and some XML – making a proper module out of it is high on my agenda.
  4. Do a better job of centralising the variables across the scripts – things like user name, password, domain name, etc. I had in mind an XML file with all the key stuff in just one place!
  5. Take feedback and refine. Comments on these scripts are most welcome.

Summary

With the release of Server 2012 and Windows 8, building a set of Hyper-V VMs is now easier than ever – and these VMs can easily be moved from server to client and back as needs dictate. The set of scripts I’ve created have helped me create lab environments quickly and easily and may help you too.

Comments most welcome!