Fun with Windows Deployment Services in WS2012 R2

Recently we’ve been having some random strangeness happening with our Windows Deployment Services (WDS) server in the office. A look around the environment didn’t uncover any “A-HA!” moments. All looked as it should. Performance counters and metrics were all where they should have been. But it didn’t change the fact that there was a noticeable, sudden downturn in performance of the WDS environment. We looked at the underlying SAN, the virtualization platform, the network infrastructure, the VMs themselves. They all were returning smiling happy faces and saying “Nothing to See Here.”

Now all this digging around did unearth some other issues that we needed to address, especially around patching of our VMs. I found a couple that somehow hadn’t been patched in over 2 1/2 years. Oops. That’s not really a good thing.  The WDS server wasn’t one of those, but it did have quite a few pending so I took the opportunity to take it offline and do some maintenance and patching (and in the process of running terminal sessions from within VM console sessions from within RDP sessions I managed to trigger updates to our SAN. But that’s a story for a different blog post. Suffice it to say it all ended up just fine).

Patches downloaded, installed, server rebooted. A quick test . . . no change in the performance. Grrrrrrrrr. But not really unexpected.

And so, in the grand tradition of IT expediency and pragmatism I had the thought “I could have built a new server faster than this.” So after consulting with a few colleagues we decided I should do just that. It allowed us to tick a few different boxes anyway, and it just happened to coincide with some unexpected free time in my schedule. So off I went!

General Approach

We decided to go with a side-by-side migration, basing the new WDS server on Windows Server 2012 R2, rather than an in-place upgrade. This was a good choice for us for lots of reasons, not least of which it is the recommended approach by Microsoft for most things. So we put together our big-picture plan, which looked like this:

  1. Do your homework. I’ve had some experience with WDS, but not massive amounts in the wild, so before I started down this path I needed to make sure I had enough knowledge to be able to confidently do the work without any major, preventable issues. I had a look through the topics found in course 20415-Implementing a Desktop Infrastructure, and then I headed off to TechNet. This article proved to be a useful starting point for me as well. It also gave me a useful basic checklist to make sure I didn’t miss any important steps.
  2. Plan and Install the Windows Server 2012 R2 VM. Using the VM configuration of the original WDS server as a starting point I made and documented the decisions about configuration and build of the VM. There were the obvious OS things like “Yes, it has to be a member of the domain”, computer name, static v. dynamic IP addressing (I went with static, so I could easily change the IP address later to take over the IP of the legacy server, thus reducing the need to reconfigure our network infrastructure), but also made decisions about some of the less obvious stuff, like how many and what type of virtual disks to use, where to store those disks (SCSI, in the shared storage, thin-provisioned), how much and what type of memory (dynamic, 2GB start-up 16GB max). Once that was done I created the VM and the disks, hooked up our WS2012R2 iso and built the VM to spec. I also tried to do as much patching as possible done here so I didn’t get interrupted when I was doing the WDS work.
  3. Set up the storage. We made the decision to make use of a few of the new features in WS2012 and WS2012R2, as well as trying to future-proof the configuration as much as we reasonably could. So what we decided in this case was to take the data disk (our second virtual disk) and set it up within Windows as part of a storage pool. If we need more storage later on we can create new virtual disks, and add them to the storage pool. Once we had that, I created a single virtual disk from that pool. Again, in the future we can extend that virtual disk if required, allowing us to relatively quickly and easily increase the storage available to hold our images. I also enabled Disk-Deduplication on the volume that was based on that virtual disk. For us, this was all about maximizing storage/minimizing storage use. WDS already de-duplicates the data in the WIMs, but it shouldn’t hurt for all of the other files.
  1. Install and configure WDS services. This was probably the most straightforward part of the process. Using the checklist I got from TechNet, I added the Windows Deployment Services role to our new VM. I wanted a new server, but not new images, so from there the configuration was really nothing more than exporting the boot and install wims from the legacy WDS server, and then adding and configuring them. On the legacy server I mapped a drive to the data drive on the new server and used that as the target for all the exports. We made the decision to only export the current wims that we use, not all the historic wims. So I really only had 4 boot wims and 5 install wims to deal with. On top of that I needed to document and copy out the unattendimage.xml files that correspond to those wims.This really wasn’t anything more than an exercise in documentation and paying attention to detail. When you export an image from WDS it makes a copy of the wim file, but does not include the other properties/configurations of the image, like unattend files. So I made sure that I documented and copied out all the unattend files that I were going to need, and then I did our image exports. Once those were done I created new images on our new WDS server, using the exported WIMs, and then going in and configuring each image to use the corresponding unattend file. Fortunately, I only had a handful of images so it wasn’t a big deal. If I were to do this again I’d spend a little time digging around in PowerShell to see if there is a command that would allow me to script that or at least do it in bulk.

     

  2. Test the new server. This was an easy one. Since we only use our WDS environment late in the day, I could take a couple of client machines and use for testing. So that’s what I did. I shutdown the legacy WDS server, and then changed the IP address of the new server to take over from the legacy server. This meant I did not have to go and change firewall, networking and DHCP settings. I restarted the WDS services and then booted up some clients.The first tests proved to be reasonably successful. The clients all successfully found the server, connected to the TFTP service and deployed images. It did reveal a couple of minor configuration errors I had made. Specifically, I had forgotten to set the boot image priorities and timeouts, and I had used the wrong unattend file for one image. Minor configuration issues that were easily fixed in about 5 minutes. The second test went as planned. No issues. However, the jury is still out on the performance issues. We won’t really know until we put it under are normal loads. It seemed quicker, but that was just the eyeball test. Regardless we have a leaner and meaner WDS server than we did before, so overall a worthwhile project anyway.
  3. Phase out the legacy server. I are quietly confident that the new server will function as required, and initial testing indicates that it will cope with the workload. So we are shutting down the original VM on a semi-permanent basis, but will leave it registered on our virtualization platform for the next 2 weeks. If we encounter any major issues we can quickly shut down the new server and spin up the original. If we are all clear after two weeks I will be delete the VM and all its files from our virtualization platform. However, I have taken a copy of the virtual disk that contained all the images for the legacy WDS server, and it is stored on external storage. If push comes to shove I can attach to the VM and get access to those wim files.
  4. Monitor and maintain. Our initial testing indicates that the new server is performing better than the last, but I haven’t received definitive proof as wet. That will likely occur when we do our first large-scale rollouts using the new WDS environment. But all signs are looking good for new.
  5. Write blog post about it. Done.

Obviously, this wasn’t a hugely technical article, more of an overview of the process and what I went through. There was a lot of good stuff in TechNet around WDS server management, so if you’re embarking on a WDS project you might want to start there.

Cheers.

NZMCT


Advertisements

Curious about Windows 10?

Windows 10 Technical Preview Fundamentals for IT Pros.

The Tech Preview (TP) for Windows 10 has been out for a few weeks now, downloaded millions of times (according to Microsoft). So what do you do with it?  It’s all well and groovy to spin up a VM,  and put Windows 10 on it and take it for a spin. You’ll be able to see the new Start Screen, take advantage of the app docking (up to 4 at a time now), the multiple desktops. All cool stuff, especially for the end-user. But if you’re the Windows Desktop team lead, or a Windows sysadmin you might be wondering “So what? What’s in it for me?” Fair enough, too.

You can dig through the Windows 10 TP doco and blogs etc.  Places like this: http://go.microsoft.com/fwlink/p/?LinkId=507620

Or this: http://go.microsoft.com/fwlink/?LinkId=507624

Or even this: http://blogs.windows.com/itpro/

And I’ll admit, there is some enjoyment to be had to dive in and dig around, delve into the details. If you have the time. And that’s always the big gotcha. IF YOU HAVE THE TIME. I know I don’t always have the time.  So if you don’t have as much time as you’d like, but you want to get an overview of “What’s new for IT Pros” in Windows 10 TP, then check out the Microsoft Virtual Academy session this Thursday/Friday (depending on your time zone).

It’s running from 6am Friday the 21st of November for all the cool kids (i.e. the ones who live in New Zealand), for 4 hours. So it will be a bit of an early start. But look at the bright side, you’ll still have most of your day left to do other cool stuff!

Windows 10 Technical Preview Fundamentals for IT Pros.

It’s running as part of the Microsoft Virtual Academy (MVA), so you will need to set up a logon for that (if you don’t already have one).  And don’t worry, if you can’t make the live broadcast, it is being recorded and will be made available ondemand through MVA at a later date.

 

Adding .Net 3.5 SP1 to an Azure VM through the Back Door.

If you’ve been working with Windows Server 2012/2012 R2 you might have noticed that you need the CD/install files handy if you want to install .NET 3.5. Which causes problems if you need that feature on an Azure VM. After a bit of digging I found this in the MSDN forums, and it has proven to be handy. I haven’t tried it enough to say that it is foolproof, but if you’re having this issue it’s worth a shot.

1. Go to Windows Update through the Control Panel.

2. Click “check for update” on the left side. It may take a while to check for the update like it did on my machine. (~5-10 min)

3. Click the “# important update is available” blue button next.

4. On the next screen you will be shown important updates that are ready to be installed. You should have an update called “Update for Microsoft .NET Framework 3.5 for x64-based Systems (KB3005628)”. With that update checked, click install on the bottom. There will be other updates available to you as well. I haven’t thoroughly tested for any combinations that specifically do/don’t work, so try at your own risk!

Assuming that update successfully install, lets go back to Server Manager and try the installation.

1 Go back to your Server Manager and in the top right corner click Manage -> Add Roles and Features.

2. Click next 4 times until you get to Features. Once in features check the box for “.NET Framework 3.5 Features” and then click next on the bottom.

3. On the next page if you see the yellow warning box to specify an alternate source path, just click ‘x’ to dismiss it. On the bottom of the page then, click install. If all goes well you should eventually see that installation succeeded.

If you’d like more detail on the why’s and wherefores:

http://support2.microsoft.com/kb/3005628

UPDATE:  Here’s an blog by an Aussie friend of mine that addresses a this issue in a non-Azure environment.

http://www.windowspcguy.net/?p=306

If you’re fighting this battle, definitely worth a read.

Using PowerShell to Register MOC VMs

A few weeks ago my friend Telmo blogged about a very elegant solution for handling the VMs that MOC courses use. I was really impressed with what he came up with.  If you are an MCT then I would definitely recommend reading that post. Thanks Telmo!

You can find it here: http://telmosampaio.wordpress.com/2013/09/01/bulk-import-vms-for-moc-classes

That made me think about some simpler scripts that I have written that may also be of use for registering VMs for any environment. I did make some tweaks to use it specifically for registering MOC VMs, but these scripts are easily portable for any environment where you want or need to bulk import VMs.

The code below gives you a script that will do two main tasks:

1. Create some standardized private virtual switches in Hyper-V. The names match the names that the vast majority of MOC VMs use. So there are more switches in there than you would likely need, but it is easily adjusted to modify the name and number of switches being created.

2. Enumerate and import all the VMs that are found in a given path. For this to work you need to feed the name of the parent folder path where all of the VMs reside. If you forget to specify a path when you run the script, there is a basic inline help that is triggered explaining the syntax.
I put a 5 second delay between each import. I have found that if I don’t then I sometimes get strange errors on the VM imports. It feels like the script is running faster than the Hyper-V administration services can process the requests. When I put in a 5 second delay, that problem basically disappears.

I’ve put the code in here twice, one version for Windows 2008 (& R2) Hyper-V servers and a version that will run on Windows Server 2012.

Windows Server 2008 Hyper-V
(requires that the Hyper-V PowerShell module from codeplex has been installed. I didn’t get fancy by doing a check, I just load it up in the first line.)

import-module HyperV
If (!$args){
” “
“Usage of the script is as follows:”
“<path>\importvm.ps1 <VM parent folder>”
” “
“<VM Parent folder> is the path to the directory that holds the Hyper-V virtual machine directories.”
“This script will automatically register all VMs that are in that path and create two private virtual switches if required.”
}
else{
#Create the private network switches
“Create the ‘Private Network’ and ‘Private Network 2’ virtual switches if required”
$switchlist = get-vmswitch | where {$_.Name -ilike “Private Network*”}
If (!$switchlist){
new-vmprivateswitch “Private Network”
“Private Network has been created.”
new-vmprivateswitch “Private Network 2”
“Private Network 2 has been created”
new-vmprivateswitch “Private Network A”
“Private Network Ahas been created.”
new-vmprivateswitch “Private Network B”
“Private Network B has been created”
}
else{
“Private Network switches may already exist. Confirm that the one you require is in the list below.”
“If it is not, you may need to create it manually.”
$switchlist
}
#List the folders in the Drives directory for the course and map them to an array.
$vms = get-childitem $args | where {$_.mode -eq “d—-“}
#Parse the array and import each VM
foreach ($vm in $vms){
import-vm -path $vm.FullName
start-sleep -Seconds 5
}
get-vm | format-table Name,State,Status -AutoSize

}

Windows Server 2012

If (!$args)
{
” “
“Usage of the script is as follows:”
“<path>\importvm.ps1 <VM parent folder>”
” “
“<VM Parent folder> is the path to the directory that holds the Hyper-V virtual machine directories.”
“This script will automatically register all VMs that are in that path and create two private virtual switches if required.”
}
 
else
{
#Create the private network switches
“Create the Microsoft Learning virtual switches if required”
$switchlist = get-vmswitch -SwitchType Private | where {$_.Name -ilike “Private Network*”}
If (!$switchlist)
{
new-vmswitch “Private Network” -SwitchType Private
“Private Network has been created.”
new-vmswitch “Private Network 2” -SwitchType Private
“Private Network 2 has been created.”
new-vmswitch “Private Network A” -SwitchType Private
“Private Network A has been created.”
new-vmswitch “Private Network B” -SwitchType Private
“Private Network B has been created.”
}
else
{
“Private Network switches may already exist. Confirm that the one you require is in the list below.”
“If it is not, you may need to create it manually.”
$switchlist
}
#List the folders in the Drives directory for the course and map them to an array.
$vms = Get-ChildItem $args -Recurse | where Name -ilike “*.exp”
 
#Parse the array and import each VM
foreach ($vm in $vms)
{
“`nImporting {0}” -f $VM.FullName
import-vm -path $vm.FullName
start-sleep -Seconds 5
}
 
get-vm | format-table Name,State,Status -AutoSize
 
 
}
 

Hopefully, this will get you started down the path to scripting more of your common Hyper-V tasks.

Cheers,

James

Enabling Data Dedup in Windows 8

I run a lot of Hyper-V VMs on my Windows 8 laptop, and my second hard drive is getting full, with all of my inactive vhd files.  I was thinking “It’s too bad Windows 8 doesn’t have volume deduplication like Windows Server 2012.” But I decided to have a bit of a nosy around the internet to see if there was a 3rd party solution.

Lo and behold! (And really, it shouldn’t surprise me by now, but it did a little bit anyway.) I found a really useful site that taught me how to hack the 2012 Dedup into my Win8 laptop.

NOTE: Doing this will put your computer in an unsupported state (due to mixing and matching SKUs of the windows code). It is up to you to assess the risk/reward equation of these actions.

Here’s the link:

http://www.scconfigmgr.com/2013/04/13/enable-deduplication-for-your-lab-environment-in-windows-8/

One of the dism commands is a little hard to copy/paste from his website, so here it is:

dism /online /add-package /packagepath:Microsoft-Windows-VdsInterop-Package~31bf3856ad364e35~amd64~~6.2.9200.16384.cab /packagepath:Microsoft-Windows-VdsInterop-Package~31bf3856ad364e35~amd64~en-US~6.2.9200.16384.cab /packagepath:Microsoft-Windows-FileServer-Package~31bf3856ad364e35~amd64~~6.2.9200.16384.cab /packagepath:Microsoft-Windows-FileServer-Package~31bf3856ad364e35~amd64~en-US~6.2.9200.16384.cab /packagepath:Microsoft-Windows-Dedup-Package~31bf3856ad364e35~amd64~~6.2.9200.16384.cab /packagepath:Microsoft-Windows-Dedup-Package~31bf3856ad364e35~amd64~en-US~6.2.9200.16384.cab

And since there is no gui for dedup in Windows 8, here’s a link to the online PowerShell help for the dedup cmdlets:

http://technet.microsoft.com/en-us/library/hh848450.aspx