Windows 10 Anniversary Update, Bitlocker, and Hyper-V

This morning, I arrived at the office to find my Windows 10 Anniversary Update desktop crashed after reboot of yesterday’s Windows Updates. No matter what I did, I couldn’t get it to boot. I took to the interwebs, and quickly found this link:

Users can’t decrypt HDD after update

The highlights from that article are:

When does a user hit the bitlocker recovery issue?

  • User has upgraded from Th1 to Th2 and then now upgrading to RS1
  • User either has Hyper-V ON or want to turn it on in RS1 after OS upgrade
  • First reboot after Hyper-V is enabled in RS1 will hit bit locker recovery – this can be soon after OS upgrade if Hyper-V was already enabled downlevel
  • Due to separate Bitlocker issue even after entering the Bitlocker key we fail to recover. Still under investigation.
  • Workaround – here are the 4 workaround that customers can choose from to avoid getting into this situation:
    • Keep Hyper-V disabled during OS upgrade and keep it disabled till servicing update on 8/23 comes through
    • Reset the Device guard RegKeys (delete the DG regkey node) and then enabled Hyper-V in RS1
    • Reset the Device guard RegKeys (delete the DG regkey node) and then upgrade to RS1 while keeping Hyper-V however customers want (ON or OFF is both fine)
    • Disable Bitlocker till 8/23

After speaking to a colleague of mine (who I’m guessing would prefer to remain nameless), I found that it is in fact possible to recover from this catastrophe (assuming you have your 48-digit Bitlocker recovery key), by going through the Windows 10 Recovery options, using your 48-digit Bitlocker recovery key, and then booting to a command prompt.

Once you’ve found the drive you want to decrypt (most likely C:), you’ll use the following Bitlocker decryption command:

manage-bde -off C:

You can use the following command to get a view of where things are, both before and after you’ve started decrypting:

manage-bde -status


Update – someone posted via the forum discussion that you can also just disable Bitlocker rather than decrypt the drive, using this command:

manage-bde -protectors -disable c:

Assuming you have a lot of data, and will re-enable in another week, you may prefer to go that route.  I’ve not tested this one, but it seems like it should work.


After you see that the drive is decrypted to 100%, you should hopefully be able to reboot back into Windows. At least this worked for me an my unnamed colleague.

After you’re in Windows, I assume you want to keep drive decrypted until said Windows Servicing update above. Alternatively, I believe you can just disable Hyper-V.

Good luck. Give me a shout if you ran into this, and/or if this helped you.

Thanks!
Janssen

Sometimes, life happens.

Some of you out there that checked in on this site regularly or had an RSS feed may have wondered what happened three years ago, and why I never posted again.

Though I can’t say it was 100% of the reason, most of it had to do with the arrival of our second child, who’s now a very lively three year old. It’s different with everyone, I know, but this time around, a much more concerted effort was needed for a couple of years to get through the wild times of the baby and toddler stages.

I think I can safely say that the clouds have begun to clear, and I’ll be starting to post again pretty regularly about many the things I used to post about, such as virtualization, PowerShell, fitness, technology, gadgets, and such. In the meantime, I’m migrating the site from Squarespace to a self-hosted WordPress site.

I’ve gone back and cleaned up the worst of the migration mess (orphan HTML randomly spewed upon pages, missing images, et cetera), but I’m sure I’ll have missed a lot. Most of the info is dated enough that I doubt it’ll matter much other than for posterity, but I did find a few items during the import that I’d like to go back and revisit soon.

PowerShell + iPhone + Prowl = SysAdmin notification nirvana

If I had to make a list of my favorite things on earth, two items near the top of the list would be Windows PowerShell and the iPhone. Being able to put those things together now is one of those game-changing experiences for me.

First, let me explain the problem at hand. I manage a lot of IT systems, and am generally on call 24×7 in the event that one of those systems goes down. For ages, I’ve constantly tried to come up with the best (and cheapest) way to be notified in the event of a critical failure, especially during night hours. Email notification won’t meet this need obviously, because you’re not going to have an email notification wake you up in the middle of the night. SMS text messages get a little closer, but still don’t meet the needs of all scenarios, especially around varying priority levels. I had just about given up… until I discovered Prowl.

Prowl is an application for the iPhone, originally designed to supplement Growl, but now becoming an awesome application by itself. The basic purpose of Prowl is to receive push notifications of your desired events via Apple’s iPhone Push Notification Service. Prowl then sounds an alert, and these sounds can vary based on the priority for which you’ve set the alert, from low to emergency.

I had first started using Prowl as a Growl forwarder, and then signed up for Google Voice alert forwarding. Both of those setups were nice, but things really began to get exciting when I found out that I could send my own Prowl alerts using PowerShell (which allows for linking up pretty much anything on earth), and even allow others to send me alerts as well.

I’ve now setup my iPhone with a very loud and obnoxious alert that will trigger in the event that it receives an emergency alert from Prowl. This could be that a mission critical system is down, or that someone important is trying to reach me immediately. Prowl even allows you to set quiet hours for receiving notifications on your iPhone, and also allows you to set an emergency override.

So, what do you need to configure Prowl to send alerts to your iPhone with PowerShell? Well, obviously, you’d need:

An iPhone

Prowl

Windows PowerShell

A Prowl.net DLL (this one isn’t required, but makes things much easier).

A PowerShell function to send your alerts (provided below).

Once you’ve configured Prowl on your iPhone and downloaded the Prowl.dll, simply import the PowerShell function and then start sending:

function Send-Prowl
{ param($Description="Default Description", $priority="Normal")
[Reflection.Assembly]::LoadFile("C:\Prowl\Prowl.dll")
$prowlclientconfig = New-Object prowl.ProwlClientConfiguration
$prowlclientconfig.ApiKeychain ="set this to your Prowl API Keychain from the Prowl website"
$prowlclientconfig.ApplicationName = "PowerProwl"
$prowlclient = New-Object prowl.ProwlClient($prowlclientconfig)
$prowlnotification = New-Object Prowl.ProwlNotification
$prowlnotification.Event = "PowerShellAlert"
$prowlnotification.Priority = $priority
$prowlnotification.Description = $description
$prowlclient.PostNotification($prowlnotification)
}

In the example provided, the only thing you have to change
is your Prowl API keychain value (unique to your iPhone, and found on the Prowl website), and the file location for your Prowl DLL . Everything else can be modified as desired,
but doesn’t have to be. Once you have
the function setup, you can start incorporating Send-Prowl into various monitoring
tasks, from scheduled tasks, OpsManager triggers, etc. – you could even have it tied to a home automation system to send you alerts when your front door opened.

It’s also a way to have your closest contacts reach you in
the event of an emergency. Assuming they
have PowerShell and the Prowl.dll, they can just contact you by using something
like:

Send-Prowl -priority Emergency –description “Please call me ASAP! Water line just broke!!!”

By the way, before anyone critiques the sloppiness of the PowerShell script, this script is meant only as a quick-start example to show people how to use the DLL, as I didn’t find any example Prowl PowerShell code on the internet (the examples were in C#). You’ll want to customize it to your needs.

Happy Prowling!

Janssen

GoogleVoice + SIP phone + Linksys PAP2 = free unlimited long distance home phone service

For years, I’ve been seeking out the cheapest way to get unlimited local and long distance calling for home phone service. I was a very early subscriber to Vonage, and later switched to Skype and bought various  Skype USB-to-RJ11 devices to allow internet phone calls to ring in on regular phones around the house. After a couple years, we finally gave up and went to primarily just using an AT&T cellular family plan with a lot of minutes.

Last year, my employer (Indiana University) invested substantial infrastructure in Microsoft Office Communications Server (OCS), which provides VOIP services integrated directly with our Microsoft Exchange environment. Missed call notifications and voicemail go directly into our mailbox, etc., and it’s a very nice system. In fact, I have a Polycom CX700 sitting on my desk at home, allowing me to work from home and have my work number ring in directly to my home office.

So that’s all well and good, but what if you want to have that same kind of experience for non-business calls – and for really cheap? Well, in the past, Vonage or Skype were probably the best/cheapest solutions, but with Google Voice coming onto the scene, one can setup a pretty nice system for virtually no cost (after initial setup). The basic idea is this: there are a lot of VOIP providers out there which allow free inbound calls, and charge pennies per minute for outbound calls. However, with Google Voice, one can make *every* call an inbound call, and save those last pennies. With Google Voice, any time you want to make an outbound call, you just give that number to your Google Voice service, either through a webpage, iPhone app, etc., and they call you first. Then, once you pick up the phone, they dial the party on the other side. Voila – instant unlimited free long distance.

It’s possible that at some point, VOIP companies are going to get upset at Google Voice and their customers for using their services like this, but in the meantime, it’s a nice setup.  So what do you need to get started?  Well, basically the components are:

1)      High Speed Internet Access (this is a given, since we’re making VOIP calls)

2)      Google Voice (this is invite-only, but if you ask for an invite, they usually turn it around within a couple weeks)

3)      A VOIP provider with free inbound SIP calls (I’m using sipgate).

4)      A box to convert incoming SIP calls over to standard telephones (I’m using a Linksys PAP2, which you can pick up on Amazon for about $50).

5)      Traditional telephone (I’m using a 3-handset cordless model, to have a phone on each floor).

Once you have the parts, you basically just plug your Linksys PAP2 into your home router, then login to its web interface to do some basic configuration, which is well documented on sipgate’s website, and which takes under 5 minutes. After that, plug in your regular telephone into the phone port on the back of the Linksys PAP2 and test a phone call. Now you have VOIP phone service, but not free unlimited outbound calling. To get the outbound calling, simply setup your Google Voice account, and add your VOIP number to your Google Voice registered phone number list.

Compellent PowerShell Command Set

At the end of 2008/beginning of 2009, Compellent announced the release of the Compellent Command Set, which is a full-featured PowerShell snap-in to manage a Compellent SAN, as well as many tasks in Windows around the area of Disk Management. For those lucky IT administrators that have a Compellent SAN, gone are the days of having to figure out clever ways of scripting diskpart by saving out text files to Windows hosts and executing those files through psexec or some remote shell. Compellent’s snap-in provides an end-to-end tool creating LUNs, mapping them to your servers, and setting up the corresponding volumes from inside Windows. Here’s an example script to show you how easy it is to create a new LUN and bring up a new volume in Windows. To help visualize how short this script is, I’m going to paste it twice – once without comments, and once with comments. In PowerShell, code is generally so concise that the number of lines of containing comments and documentation generally outnumbers the lines of code by quite the margin.

function Create-NewWindowsVolumeFromSAN ($lunname = $(throw "LUN name required"))
{process
{
if (Get-PSSnapin -Name Compellent.StorageCenter.Scripting 2>$null) {}
else    {Add-PSSnapin -Name Compellent.StorageCenter.Scripting}
$volume = New-SCVolume -Name $lunname -Size 500g -ParentFolder MYFOLDER
sleep 3
New-SCVolumeMap -VolumeIndex $volume.Index -ServerName MYSERVER
$i=0
While(!(get-diskdevice -Server MYSERVER -SerialNumber $volume.SerialNumber) –and ($i -lt 10))
{Rescan-DiskDevice -Server MYSERVER -RescanDelay 5;$i++}
if($i -eq 10){Throw "Unable to find disk device on server!";Break}
Set-DiskDevice -Server MYSERVER -SerialNumber $volume.SerialNumber -readonly:$false
$disk = Set-DiskDevice -Server MYSERVER -SerialNumber $volume.SerialNumber -Online
$nvol = New-Volume -server MYSERVER -DeviceName $disk.DeviceName -label $lunname
}
}
function Create-NewWindowsVolumeFromSAN ($lunname = $(throw "LUN name required"))
{
#.Synopsis
#
# Creates a LUN on the Compellent SAN and maps it up to the server, which is hardcoded in this script
#.Description
#
#.Example
#
# Create-NewWindowsVolumeFromSAN MYTEST01
Process
{
#### Add the Compellent snap-in if it's not already added
if (Get-PSSnapin -Name Compellent.StorageCenter. Scripting 2>$null) {}
else    {Add-PSSnapin -Name Compellent.StorageCenter.Scripting}
### Create a new 500GB LUN in the folder called MYFOLDER
### Change Parent to meet your needs, or parameterize it in the function
$volume = New-SCVolume -Name $lunname -Size 500g -ParentFolder MYFOLDER
### Sleep a few seconds to let the LUN finish creating
sleep 3
### Map the volume to your server on the server called MYSERVER
### This name is the name of the server as displayed by your Compellent UI,
### and not necessarily the NetBIOS name of the server,
### though you should make these the same as a best practice
### Change Server name to meet your needs, or parameterize it in the function
New-SCVolumeMap -VolumeIndex $volume.Index -ServerName MYSERVER
### Create a "Rescan Disk loop in order to keep looking for the volume until it shows up in Windows
### The server name listed below is the actual NetBIOS name of the server to which you wish to map your LUN
### Change Server name to meet your needs, or parameterize it in the function
$i=0
While(!(get-diskdevice -Server MYSERVER -SerialNumber $volume.SerialNumber) –and ($i -lt 10))
{Rescan-DiskDevice -Server MYSERVER -RescanDelay 5;$i++}
if($i -eq 10){Throw "Unable to find disk device on server!";Break}
### Set the "Read-only" bit to false. This is required when scripting the online of a disk rather than using Disk Management GUI
Set-DiskDevice -Server MYSERVER -SerialNumber $volume.SerialNumber -readonly:$false
### Bring the disk online. In Windows 2008 and above, all SAN disks are always first presented to Windows in Offline mode.
$disk = Set-DiskDevice -Server MYSERVER -SerialNumber $volume.SerialNumber -Online
### Initialize the disk and format the volume, giving it a volume label to match your LUN name.
$nvol = New-Volume -server MYSERVER -DeviceName $disk.DeviceName -label $lunname
}
}

For more information on scripting with the Compellent PowerShell Command Set, check out the user group at http://compellentpowershell.groups.live.com. Happy scripting!

Janssen

Change is in the air

A lot of time has passed since my last post, and wow – things have changed! Ushering in the era of change with the candidate of change, the world as I knew it in 2008 has changed dramatically in 2009. On a personal note, my wife and I had our first baby (a 5lb 9 oz baby boy) in March. Talk about a change in routine! Also, I received the Microsoft MVP award for Virtualization, due to work with System Center Virtual Machine Manager. You’ll be seeing a lot of posts in the coming days about what’s coming soon in VMM R2 – But on to the matters I have generally blogged about:

Nearly every technology item I’ve posted on in the past year has changed dramatically. A few examples:

  • Scripting against a Compellent SAN (with the introduction of the Compellent PowerShell Command Set)
  • Scripting Failover Clustering (with the introduction of the Win2K8 R2 RC and its corresponding + PowerShell Failover Cluster cmdlets)
  • Scripting Windows Disk Management (with Compellent’s new Command Set for Windows Disk Management)
  • Scripting the creation of virtual machines from SAN replays using System Center Virtual Machine Manager R2 (which is on the verge of releasing a Release Candidate in the coming weeks)

The release of the aforementioned technologies has rendered virtually every one of my previous blog posts obsolete. However, the good news is that I’ll be posting a series of updated scripts demonstrating how much easier it is to script the creation of a clustered virtual environment in 2009. Stay tuned!

Managing an HA Hyper-V Infrastructure: Part 3 – Scripting DiskPart with PowerShell

In my last installment of the “Managing an HA Hyper-V Infrastructure” series, I discussed getting volumes provisioned on the SAN.  Now that we have the volume presented to Windows, the next is to setup the disk.  In Windows 2008, this means bringing the disk online, initializing the disk, partitioning the disk, formatting the volume, and giving the volume a label.

For the longest time, I struggled with figuring out how to do this via script.  In Disk Management, this process is very easy, but with scripting, not so much.  From what I can gather, not many people out there are scripting with DiskPart, or if they are, they aren’t writing about it online.  After weeks of searching, and
finding little to no information, I decided to set out on writing my own PowerShell version of DiskPart.  Due to the complexity of this topic, I plan on dividing this one out over a few posts.  Without further ado, let’s dive in.

The first issue with DiskPart is that it has two ways it can be run, both of which aren’t very useful to us out of the box:
interactive mode and scripted mode.
Interactive mode, of course, isn’t useful for scripting.  Scripted mode requires the use of a pre-existing text file from which to call and execute a set of commands.  Since our text file is going to be different every time we need to run it based on volume name, disk number, etc., this makes DiskPart very limited in what it can do from an automation perspective.  So how can be work around this limitation?
OK, if you’ve been reading any of the previous posts, by now you already know
the answer.  Right again, it’sPowerShell.

Much like the way I created the CompCU wrapper in the previous post, we can create a PowerShell wrapper for DiskPart to allow you to run it in scripted mode, but work it interactively at the same time by passing variables, running through loops, etc., increasing flexibility exponentially.  The basic syntax for scripted DiskPart is:

DiskPart /s filename.txt

Since we have to have a file from which to call DiskPart, we need to dump all of the commands we’d like to run into a temp file, execute it, and then discard the temp file.  Here’s how we can do that:

function Run-DiskPart {
param([array]$commands)
$tempfile = [System.IO.Path]::GetTempFileName()
foreach ($com in $commands)
{ac $tempfile $com}
$output=DiskPart /s $tempfile
ri $tempfile
$output
}

Here’s an example of how we might call this function.  Let’s say that from a series of steps in my script, I know that I need to get detailed disk information on disk 3:

                $Num = 3
Run-DiskPart “select disk $Num”,”detaiL disk”

Now, let’s step through this one line at a time.  First:

                param([array]$commands)

We are allowing as input any number of commands which will find their way into our script.  In the example above, we have two commands: “select disk 3”, and “detail disk”.

Second:

                $tempfile = [System.IO.Path]::GetTempFileName()

This line is actually setting up a temp file to be used by DiskPart.  Usually, this file will live in a path something like:

                C:\Users\<username>\AppData\Local\Temp\tmp7FD2.tmp

Third:

                foreach ($com in $commands)

Here, we’re simply looping through each object in our array.  Again, from the earlier example, we have to objects: “select disk 3”, and “detail disk”.  The first time through the loop will deal with “”select disk 3”, and the second loop through will deal with “detail disk”.

Fourth:

                {ac $tempfile $com}

Here, we are adding the first command, “select disk 3” to line one of our temp file, tmp7FD2.tmp.  Since we’re inside a loop, the code will then come back through and add our second line, “detail disk”, to line two of our temp file.

Fifth:

                $output=DiskPart /s $tempfile

Here, we are actually executing DiskPart, using the script we just created, and capturing all output into the $output variable.

Sixth:

                ri $tempfile

Now that we’ve finished using our temp file, this line deletes the file.  In PowerShell, ri is an alias for remove-item, which is the equivalent of del in standard command prompt syntax.

Finally:

                $output

This line just passes back all of the output we captured when originally running DiskPart.  This output is still all just a bunch of strings, and as such, it will need a lot of parsing to become useful data.  We’ll look more at how we do that in the next installment.  For now, just know that DiskPart CAN be scripted on the fly, with full variable support, loops, etc., and can therefore become an invaluable piece in our overall scripting solution.  If you made it this far, hopefully you’ve
found how you can put this function to use in your environment. Until next
time…

Good luck, and happy virtualizing!

Managing an HA Hyper-V Infrastructure: Part 2 – Provisioning SAN Storage (on a Compellent SAN)

We’ve had a Compellent SAN for about six months, and I love 95% of the things about it.  Part of the 5% that I dislike though is no native PowerShell support (yet – stay tuned for that).  Compellent does offer a Java based scripting tool though called CompCU.jar.

Much like diskpart, ipconfig, dir, and other great and useful tools, CompCu.jar is a command line based utility which can’t easily be scripted with variables and for-each loops, and which doesn’t give output that easily lends itself to parsing.  Enter (drum roll)… PowerShell of course.

One of the (thousands of) great things about PowerShell is that with a bit of ingenuity and elbow grease you can convert just about anything to run with a PowerShell wrapper.

Here’s an example of the basic syntax for running a CompCu command on the SAN:

java -jar compcu.jar -host sancontroller -user admin  –password mypass -c “server show”

Of course the only part that ever changes is the part between the quotes at the end.  Therefore, the first order of business is to wrap everything else in a function.

Here’s how I setup the PowerShell wrapper for CompCu.jar

function san
{
param ($mystring)
cmd /c java -jar "compcu.jar" -host "dns.or.ip.of.san" -user sanusername -password 'sanpassword' -c ""$mystring""
}

Now, when I want to execute a command on the SAN, I just type something like:

san "server show"

That’s a lot less typing!  But wait, there’s more!  Now that we have the wrapper, and we’re at a PowerShell prompt, we have the full power of PowerShell at our fingertips.  So let’s say that one of the most common things we do is create a volume on the SAN and map that to all five of our cluster servers.  With a couple lines, we can extend our first function to a new super-function:

function clusterlun
{
param ($lunname)
san "volume create -name $lunname -readcache true -writecache true -size 500g -folder CLUSTER -server CLUSTERSERVER1"
san "volume map -name $lunname -server CLUSTERSERVER2 -force"
san "volume map -name $lunname -server CLUSTERSERVER3 -force"
san "volume map -name $lunname -server CLUSTERSERVER4 -force"
san "volume map -name $lunname -server CLUSTERSERVER5 -force"
}

Now, each time we want to setup a new Cluster LUN on the SAN, we can just type:

clusterlun MYLUNNAME

As opposed to:

java –jar compcu.jar -host server1 –user admin  –password mypass –c "create -name MYLUNNAME -readcache true -writecache true -size 500g -folder CLUSTER -server CLUSTERSERVER1"

java –jar compcu.jar -host server1 –user admin  –password mypass –c "volume map -name MYLUNNAME -server CLUSTERSERVER2 -force"

java –jar compcu.jar -host server1 –user admin  –password mypass –c "volume map -name MYLUNNAME -server CLUSTERSERVER3 -force"

java –jar compcu.jar -host server1 –user admin  –password mypass –c "volume map -name MYLUNNAME -server CLUSTERSERVER4 -force"

java –jar compcu.jar -host server1 –user admin  –password mypass –c "volume map -name MYLUNNAME -server CLUSTERSERVER5 -force"

That’s the difference between 684 characters (with spaces) and 20 characters for each LUN map (disclaimer – yes, I know there are ways the java version could be shortened with a bit more effort, but I’m trying to prove a point – no matter WHAT you do, PowerShell will ALWAYS be shorter, AND more flexible ).  But wait, that’s not all!

Let’s say you already have a cluster up and running with 30 mapped volumes, and you want to add another cluster node.  Normally, this involves an enormous amount of work to map all 30 LUNs to another server.  From the web-based GUI, it would probably take 15-20 minutes.  But with PowerShell, you can do that in 30 seconds or less with TWO lines of code.  That’s right.  TWO LINES OF CODE!!!! Simply put the names of your existing volumes into a text file, and run the following:

$myvolumes = get-content myvolumes.txt
foreach ($vol in $myvolumes) {san "volume map -name $vol-server CLUSTERSERVER6 -force"}

Voila!   Your server is now all mapped up and ready to be added to the cluster.

In summary, you can see that knocking out the scripting portion on the SAN is the first and integral part in getting your "scripted Hyper-V cluster solution" ready for prime time. And PowerShell comes through with flying colors in making that piece easy!  I don't have experience with other SANs, so I don't know what their scripting options are, so your mileage may vary, but believe me, it's worth the time in getting this figured out early on.  Every minute you spend doing this manually is a minute wasted, and eventually, you'll get so sick of doing things manually that you'll finally break down and script it.  So why not script it from the beginning?

<

p class=”MsoNormal” style=”margin: 0in 0in 10pt;”>Good luck, and happy virtualizing!

Managing an HA Hyper-V Infrastructure: Part 1 – Overview

So it has officially been over a year since my last post, but I have a good excuse.  I’ve spent much of the last year building out a pretty large Highly Available (HA) Virtual Infrastructure, with over 100 Hyper-V Virtual Machines across three clusters, all running on Virtualized Storage (on a Compellent SAN).  It’s not easy to scale out to 100+ machines quickly, especially when many of the tools are in their early stages of development.  Luckily, my old friend PowerShell saved the day on many occasions, becoming the thread that tied our whole solution together.  So what are the pieces involved in setting up a Virtual Infrastructure?  Well, in my environment, those tools were:

·         Windows Server 2008 Datacenter Edition
·         Windows Failover Clustering
·         Hyper-V
·         System Center Virtual Machine Manager 2008 (beta at the time)
·         Compellent Storage Center 4
·         Windows PowerShell

So what does it take to deploy an HA VM in Hyper-V?  Well, once you have a Hyper-V cluster up and running (there are many posts/articles/whitepapers already floating about on that topic, so I’ll skip it here), there a series of steps one must go through, which can be fairly painful when first learning, but which become lightning fast once you get through the learning curve (and once you decide to do EVERYTHING using PowerShell).  Here’s the general workflow:

First, everything at the storage level:

1)      Create a volume for your virtual machine on a SAN
2)      Map  that volume to all of the nodes of your cluster
3)      Bring the disk online on one node of your cluster
4)      Format and name the volume on one node of your cluster
5)      Rescan the disks on each node of your cluster
6)      Add the disk to your shared cluster storage

Next, the actual virtual machine setup (using SCVMM in our environment):

1)      Refresh the Host Cluster in Virtual Machine Manager in order to make it aware of your new SAN storage
2)      Choose from a pre-existing sysprepped virtual machine template (I’ve already set these up, and I can choose from Windows 2003, Windows 2008, etc., as well as my number of procs, amount of RAM, etc. )
3)      Allow Virtual Machine Manager to decide the best host for deployment using Intelligent Placement.
4)      Choose the disk created from the previous storage steps
5)      Kick off the Deployment
6)      Start up the machine
7)      Complete the Sysprep wizard from inside the VM

Sure, that may seem like a lot steps (and it did to me too when we first started), but you can script almost EVERY step using PowerShell, so in the end, this whole process can be completed in under 10 minutes, with about 3-4 total minutes of user interaction.  Just think about that.  Someone calls you up and says they have a new database server that needs to be up by next week (put a rush on it!), and you don’t have to rush to spec servers, get quotes , find out about availability, check shipping times, etc., and HOPE you can get it racked in time.  You just spend four minutes on spinning up the VM, (optionally wait three days so they don’t think you can actually set machines up this fast, to prevent them from taking it for granted), call them back, and tell them it’s ready.

The magic of the whole solution lies in the scripting in order to  tie it all together.  Working through all of the steps manually would take well over an hour per machine (still better than taking weeks to buy a physical server, but much longer than I want to spend), especially when you start factoring in manually mapping volumes to 5+ nodes of a cluster.  However, not a lot of people are using these technologies yet, so there wasn’t much guidance in scripting that area.

My main hope over the next several posts is to provide what I’ve learned along the way, along with the scripts I’ve written, to help more people hop on board the virtualization train.  I’m certain that it’s picking up steam, and over the next year, you can either join in or be left behind.  Good luck, and happy virtualizing!

Powershell and SMS Part 2 – parsing bad MIF files

I’ve been working on my SMS site this weekend, and had a couple issues that would have taken a bit of time to deal with. However, given a couple lines of Powershell, I turned minutes of work (which turn into hours when scaled) into instant gratification.

Example 2:

In the course of rebuilding my SMS site last week, I managed to encounter some documented bugs, and long story short, I had a slew of bad MIF files that I needed to contend with. The gist of what needed to be done was to open each MIF file in a text editor and find the computer name associated with the bad MIF. When dozens of these start showing up, it takes a lot of time to open each file – (OK, not THAT much time, but again, as the problem scales, it does become significant).

Enter Powershell:

With Powershell’s ability to use WHERE-OBJECT(?) and FOREACH-OBJECT(%),
one can parse the whole directory in a couple of seconds and end up with only the computernames:

gc F:\SMS\inboxes\auth\dataldr.box\BADMIFS\*.mif | ? {$_ -like “*netbios*”} | % {$_.split(“<> “)} | ? {$_ -like”*BL-*”} | sort -unique

So how does it work? First, let’s break down the commands:

gc – this is an alias for Get-Content, which basically just
reads a file

? – this is an alias for Where-Object – in other words, a filter

$_ –  this is the way Powershell
interprets “the current object” in the pipeline

% – this is an alias for Foreach-Object – in other words, a loop

sort – I’m using sort here because it has a –unique parameter, which I use to
return a single instance

So the English version of the command above is:

1) Read all files with a MIF extension in this directory

2) Only return lines which contain the word netbios

3) Split those lines up anywhere there’s a space, a <, or a >.

4) Only return lines which contain “BL-“ (all my computer names contain these letters).

5) Return only unique instances of that computername.

Most people probably won’t be able to use THAT particular code, but I just wanted to illustrate how powerful Powershell is when it comes to trudging through hundreds of lines of text to give you just what you’re looking for.