Building a SharePoint 2007/2010 development environment – Part IV: Automated deployment

In the first three parts of this series I covered the project objectives and the system design, then turned my attention to the Hyper-V host image build. In this section I will look at automating deployment of that host operating system. This is lengthy, but there’s a lot to cover.

Before I begin, I need to reiterate a “gotcha” that I stumbled across during the pilot. If you’re thinking of testing this out by adding the Windows Deployment Services role to a machine that’s using Internet Connection Sharing (ICS), think again. They don’t play nicely together. Rather, you’ll be able to deploy the physical machines but any ICS recipient network adapters will be left without connectivity. If you only have one physical machine for testing, consider deploying WDS to a new virtual machine or adding the role within an existing virtual machine.

Imaging

To capture the host OS image we need Windows Deployment Services (WDS), which is a Server Role in Windows Server 2008 R2 (and Windows Server 2008, but we won’t be bothered with earlier incarnations of WDS, RIS or ADS). To specify configuration options during deployment we will attach an unattend file to the captured image. We’ll create it using the WAIK for Windows 7, which includes Windows System Image Manager (Windows SIM).

Preparation

Before we begin, note that WDS needs to be deployed in an Active Directory domain (as a member or a DC) with DHCP and DNS.

  • To install WDS, add the Server Role through the Role Summary pane in Server Manager
    • Once launched, configuration options can be selected for WDS, such as default naming patterns and default unattend files. You will not be able to commit any configuration changes unless they are made by a Domain Administrator. If this is a test environment and you are unable to get Domain Admin rights, WDS can still be used with a bit more of a hands-on approach (manually naming servers and joining to the domain, etc.). These configuration options are covered in more detail below
  • To download the Windows Automated Installation Kit for Windows 7 (WAIK), visit microsoft.com and grab the latest version
    • Mount the ISO file and install Deployment Imaging Servicing and Management (DISM), which includes the Windows System Image Manager (SIM)
      • A good ISO mounting tool is Magic ISO Maker. Daemon Tools jumped the shark
  • To use WAIK, you will need to have access to Windows Server 2008 R2 installation media
    • If the server is a virtual machine, consider attaching ISO files of the installation media as optical drives on the IDE controllers in the virtual machine’s settings, as this may make things easier
      • I have created two additional optical drives in my WDS virtual machine, with a Windows 7 ISO file mounted in one virtual optical drive and a Windows Server 2008 R2 ISO file mounted in the other. This allows me to maintain unattend files for both operating systems without having to mess about with real optical/removable media
  • Ensure that both the WDS machine and the soon-to-be-captured Hyper-V host are connected to the network
  • If testing WDS on a live network, be certain that there are no other PXE boot servers on the environment before adding the WDS role, as this may result in network installation chaos otherwise

Configure WDS

This guidance covers some of the settings in WDS that are applicable to this use. I don’t touch on all of them. It should go without saying that WDS deployment should be considered in much greater detail than these summary steps and that administrators should familiarise themselves with WDS and WAIK before unleashing them. That said…

To configure WDS, log on to the server as a domain administrator and launch Server Manager. Expand the Windows Deployment Services node in “Roles”. Right-click the server that you want to configure and select “Properties”.

PXE Response

Choose how strictly you want to control deployment of images. If this is a test environment, configure the role for known and unknown devices. Ideally this configuration is a bit more considered for production. Note: this is distinct from the PXE Boot Policy, which governs the behaviour of the PXE boot process rather than restricting which devices can be booted in to WDS. Think of this as the device setting and PXE Boot Policy as the user setting.

Client Naming Policy

These settings control the auto-generated naming format. For instance, “Dev-%8Username-%02#”, breaks down as follows:

  • “Dev-”
  • “%8” specifies an eight-character variable
  • “Username” is the variable, meaning that the first eight characters of the user’s name will be used in the computer name
  • “-” adds a hyphen
  • “%02#” specifies a two-character auto-incremented number at the end of the string

Computer Account Location

Specify an OU where new instances of the image should be created.

PXE Boot Policy

Configure this setting to preference. It controls the behaviour of the PXE boot once it has been initiated (either from a one-time boot menu or BIOS boot order change). Once in the PXE boot a DHCP lease is acquired, followed by the behaviour defined here. PXE can either abort and continue with the next BIOS boot option, automatically proceed or prompt the user to press F12 to confirm PXE boot. Think of this as the user setting and PXE Response as the device setting. If unsure what to choose, prompting is probably the best option to choose.

Default Boot Image and Default Unattend file

To simplify things we attached an unattend file directly to the captured image, as spelled out in John Howard’s, slipstreamed Hyper-V article. The unattend file doesn’t exist yet, as we haven’t delved into WAIK yet. For now it’s sufficient to know that these WDS configuration settings determine distinct boot images and default unattend files for different processor architectures. Since we’re attaching the unattend file to the image directly we don’t need to worry about providing values for these settings.

It’s worth reviewing the overlapping options in WAIK and WDS for these defaults settings, as it’s far from straight-forward. TechNet covers this beyond the scope of this article.

Joining a Domain

This setting allows for the newly deployed machines to be automatically joined to the domain.

Network settings

Specify DHCP, Multicast, Transfer Settings (throttling), domain discovery and the UDP port range. Default settings should suffice in a test environment. Approach these choices with care if this environment contains any valuable resources beyond these test machines.

Prepare the Capture Image in WDS

The Capture Image is a PXE-booted version of WinPE specifically designed for capturing custom install images. When PXE booting to capture an image, make sure to select this image rather than a boot image.

  • Mount an ISO or insert install media for Windows Server 2008 R2
    • As mentioned above, it might be easiest to add the ISO as a DVD drive on the VM’s IDE Controller. This will also be useful for WAIK configuration later
  • Add the Boot WIM to the Boot Images directory
    • Right-click Boot Images in WDS and select “Add Boot Image”
    • Make sure to select the right CPU architecture for the boot image
      • Note: if you forget to do this, you can capture an x64 OS with an x86 Capture Image, but it may be slower to do so. Also, an x64 Capture Image will not be bootable unless the machine has an x64 processor
  • Create a Capture Image from the Boot Image
    • Right-click the newly added boot image in WDS and select “Create Capture Image”
    • This will launch a wizard with a link to a help file if the wizard is unclear
    • This is necessary for creating a custom install image in WDS

Generalise the host build

We’re finally ready to get back to the host build. Note: if the host has been built as a virtual machine (as recommended at the top of part III of this series), take a snapshot of the virtual machine before running SysPrep so that the reseal count is not incremented for future updates to the build.

To generalise the host build, run sysprep /oobe /generalize /shutdown. This can also be done from the GUI by double-clicking sysprep.exe.

Capture the install image

Start the host machine and invoke the one-time boot menu (commonly F12).

  • Select PXE, NIC or network boot (terminology varies)
    • Depending on the configuration of the Windows Deployment Services (WDS) server it may be necessary to press F12 again to confirm PXE boot
      • If this isn’t done, the machine will boot from hard disk and the machine will need to be SysPreped again
  • Select the Capture Image that was created above
    • Again, remember to select the correct processor architecture
  • In the Windows Deployment Services Image Capture wizard, choose a location to save the new image
    • This location can be the same disk that’s being captured. I suggest creating a folder called D:Captured Image so that the directory can be removed with the post-deployment script below
      • Note: the drive letter will not be “C:”, as that’s the WinPE Capture Image that we’re “in” at this point. The System disk will probably appear as “D:”
    • Allow time for the image to be captured locally and then for it to be transfered to WDS
  • In my experience, the captured image does not appear in WDS immediately. I’ve needed to re-launch Server Manager to view it and in some cases a reboot was necessary
  • If for some reason the network transfer of the image to WDS fails, it can be manually copied to the WDS server and added, but make sure to reboot the server as described above before taking this step or the images may be duplicated and this could get confusing

Creating the Unattend file

Open the Windows System Image Manager from the Start > All Programs > Microsoft Windows AIK menu.

  • In the Distribution Share pane, select or create a distribution share in the location of your choice. I created mine in D:WAIKDistributionShare
  • In the Windows Image pane, choose Select Windows Image and choose the Windows Server 2008 R2 sourcesinstall.wim file from install media. Select the Standard Full edition when prompted
  • Paste the XML below in to a text file and save it as DevBuild.XML
  • In the Answer File pane, open DevBuild.XML below as a starting point for your selections

DevBuild.XML

<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
 <servicing>
 <package action="configure">
 <assemblyIdentity name="Microsoft-Windows-Foundation-Package" version="6.1.7600.16385" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="" />
 <selection name="Microsoft-Hyper-V" state="true" />
 <selection name="VmHostAgent" state="true" />
 <selection name="Microsoft-Hyper-V-Management-Clients" state="true" />
 <selection name="WirelessNetworking" state="true" />
 <selection name="CoreFileServer" state="true" />
 <selection name="SearchEngine-Server-Package" state="true" />
 </package>
 </servicing>
 <settings pass="windowsPE">
 <component name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <SetupUILanguage>
 <UILanguage>en-GB</UILanguage>
 </SetupUILanguage>
 <InputLocale>en-GB</InputLocale>
 <SystemLocale>en-GB</SystemLocale>
 <UILanguage>en-GB</UILanguage>
 <UserLocale>en-GB</UserLocale>
 </component>
 <component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <DiskConfiguration>
 <WillShowUI>OnError</WillShowUI>
 </DiskConfiguration>
 <Display>
 <ColorDepth>32</ColorDepth>
 <HorizontalResolution>1280</HorizontalResolution>
 <RefreshRate>60</RefreshRate>
 <VerticalResolution>800</VerticalResolution>
 </Display>
 <ImageInstall>
 <OSImage>
 <InstallToAvailablePartition>true</InstallToAvailablePartition>
 <WillShowUI>OnError</WillShowUI>
 </OSImage>
 </ImageInstall>
 <UserData>
 <ProductKey>
 <WillShowUI>OnError</WillShowUI>
 <Key>XXXXX-XXXXX-XXXXX-XXXXX-XXXXX</Key>
 </ProductKey>
 </UserData>
 </component>
 </settings>
 <settings pass="specialize">
 <component name="Microsoft-Windows-IE-ESC" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <IEHardenAdmin>false</IEHardenAdmin>
 <IEHardenUser>true</IEHardenUser>
 </component>
 <component name="Microsoft-Windows-IE-InternetExplorer" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <CompanyName>Your Company</CompanyName>
 <DisableAccelerators>false</DisableAccelerators>
 <Home_Page>http://yourhomepage.com</Home_Page>
 <IEWelcomeMsg>true</IEWelcomeMsg>
 <SuggestedSitesEnabled>false</SuggestedSitesEnabled>
 </component>
 </settings>
 <settings pass="oobeSystem">
 <component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <Reseal>
 <ForceShutdownNow>false</ForceShutdownNow>
 </Reseal>
 </component>
 <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <OOBE>
 <HideEULAPage>true</HideEULAPage>
 <ProtectYourPC>3</ProtectYourPC>
 </OOBE>
 <StartPanelLinks>
 <Link0>C:Program Files (x86)Mozilla Firefoxfirefox.exe</Link0>
 <Link2>C:Program Files (x86)SafariSafari.exe</Link2>
 <Link1>C:Program Files (x86)Opera 10 Betaopera.exe</Link1>
 </StartPanelLinks>
 <TaskbarLinks>
 <Link0>%windir%system32notepad.exe</Link0>
 <Link1>C:Program Files (x86)code4wardRoyal TS</Link1>
 <Link2>C:Program Files (x86)Internet Exploreriexplore.exe</Link2>
 </TaskbarLinks>
 <UserAccounts>
 <AdministratorPassword>
 <Value>encrypted</Value>
 <PlainText>false</PlainText>
 </AdministratorPassword>
 <LocalAccounts>
 <LocalAccount wcm:action="add">
 <Password>
 <Value>encrypted</Value>
 <PlainText>false</PlainText>
 </Password>
 <DisplayName>SourceShare</DisplayName>
 <Name>SourceShare</Name>
 </LocalAccount>
 </LocalAccounts>
 </UserAccounts>
 <TimeZone>GMT Standard Time</TimeZone>
 </component>
 </settings>
 <cpi:offlineImage cpi:source="wim:z:/sources/install.wim#Windows Server 2008 R2 SERVERSTANDARD" xmlns:cpi="urn:schemas-microsoft-com:cpi" />
</unattend>

Make changes to this file as needed for your environment and save the modified file. I highly recommend reviewing these selections for suitability in your environment. Some sections like the license key and passwords (bolded above) have been replaced with nonsense values. It’s also worth reviewing the options that I haven’t selected. The Windows SIM Help documentation is excellent and it should be a quick learning curve.

Attach the Unattend file to the image in WDS

In the WDS Install Images node, expand the relevant Image Group, find the captured image and right-click to select the Properties pop-up. At the bottom of the General tab there’s a tick box for allowing the image to install in unattended mode and a file selection button for picking the unattend file created above. This will apply the Unattend settings to our captured, sysprep’d image when it’s deployed.

Create the Post-deployment PowerShell configuration script

Before I begin this section, I have to disclaim that my scripting skills are fairly remedial. That said, these scripts have done the trick for us and have saved our support team a good deal of time reconfiguring environments manually.

These steps are necessary because only certain things can be specified in the System Image Manager. For instance, it is possible to configure network adapters and it is possible to add Hyper-V but it is not possible to add Hyper-V, create Hyper-V networks and then configure IP properties for the host’s new network adapters on those Hyper-V networks. To this end, the unattend file above specifies only the addition of the Hyper-V role and this script automates the next two steps. Additionally, this script will create the Source files share on the host machine (as discussed in part II of this series) and remove the local “Captured Image” directory that was created when WDS captured the image to the local drive.

  • Create a folder called “Automate” or similar
  • Visit the PowerShell Management Library for Hyper-V Codeplex page and download HyperV.zip
    • Run the installer. The script below needs to run from the same directory as hyperv.format.ps1xml and hyperv.ps1
  • In the “Automate” folder create a batch script called CreateSourceShare.bat, as follows:
c:
MKDIR C:Source
NET SHARE Source=C:Source /GRANT:"Authenticated Users",FULL
ICACLS C:Source /GRANT SourceShare:F
RMDIR "c:Captured Image"
  • Create a PowerShell script called HyperVNICAndShareScript.ps1 with these contents:
netsh interface set interface name="Local Area Connection" newname="Virtual Network Switch"
. .hyperV.ps1
New-VMExternalSwitch "Hyper-V External Network" -ext "Broadcom"
Start-Sleep -s 5
New-VMInternalSwitch "Hyper-V Internal Network"
Start-Sleep -s 5
New-VMInternalSwitch "Hyper-V ICS Network"
Start-Sleep -s 5
netsh interface set interface name="Local Area Connection" newname="External Network Connection"
netsh interface set interface name="Local Area Connection 3" newname="Internal Network Connection"
netsh interface set interface name="Local Area Connection 4" newname="ICS Network Connection"
netsh interface ipv4 set address name="Internal Network Connection" source=static address=192.168.200.1 mask=255.255.255.0
C:AutomateCreateSourceShare.bat

Deployment

At long last we are ready to test deployment of the captured image to a target machine. Start the host machine and invoke the one-time boot menu (commonly F12).

  • Select PXE, NIC or network boot (terminology varies)
    • Depending on the configuration of the Windows Deployment Services (WDS) server it may be necessary to press F12 again to confirm PXE boot
  • Select the x64 boot image for Windows Server 2008 R2
  • The WinPE installation process will be nearly identical to installation from media – just make sure to select the captured image when prompted
  • Once the installation has completed, run PowerShell as Administrator and set the execution policy to allow remote-signed scripts. For more information see Technet:
Set-ExecutionPolicy RemoteSigned
  • Press “Y” to accept the policy change
  • Run HyperVNICAndShareScript.ps1
  • Confirm that settings match the values assigned in the scripts

Manual post-deployment configuration tasks

Various settings

It’s possible that some of these settings can be automated, but we opted to configure them manually rather than spending time testing the automation of them. They will all be revisited in a later phase.

  • Make sure that the BIOS has Hardware Assisted Virtualisation and Data Execution Prevention enabled
  • Turn on Write-caching and turn off Write-cache Buffer Flushing on the physical disk’s hardware  policy
  • Set Hyper-V default locations as desired. I have chosen:
    C:Hyper-VVirtual Hard Disks
    C:Hyper-VVirtual Machines
  • Disable IPv6 on the network adapters. SharePoint in Hyper-V guidance suggests this is a good idea, as I’ve commented on before
  • Set up Internet Connection Sharing from the host’s external network connection to the host’s ICS network connection. By default we share HTTP, HTTPS and RDP

Drivers

We reduced our WDS/WAIK testing time by skipping driver installation automation. As a work-around we are capturing the host image with driver installer files included so that they can be quickly installed post-deployment. We will be introducing automated deployment in a future phase.

Role-based Authorisation and local administration rights

It may also be desirable or necessary to configure role-based authorisation for Hyper-V. John Howard has produced excellent guidance on the model in five parts. This is a link to the fifth. If this is not a requirement then don’t forget to make the recipient of the build a local administrator, as this will be required if role-based authorisation is not configured.

Import virtual machines

As a part of a routine deployment the base virtual machine would be imported, booted up and tested before it’s handed over to the recipient, but since we’ve not built that machine yet, I’m skipping that step for now. The virtual machine build will follow in part five of this series.

2 thoughts on “Building a SharePoint 2007/2010 development environment – Part IV: Automated deployment”

Leave a Reply

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