July 2011 archive

Dr. iSCSI or How I learned to stop worrying and love virtual distributed switches on vSphere V5

Intro

It’s July 12th 2011 around 2:30pm EST as I start to write this. Anything interesting in the world of VMware virtualization go on today? :)

Riiight, VMware vSphere Version 5 has been announced! Along with many other products from VMware. Definitely go to  VMware.com and EMC.com to see all the “awesomesauce” as one crazy Canadian puts it. <\shameless_plug>

As with everyone else’s blog, these words are my own and reflect my state of mind and not that of my employers. (RSA, the Security Division of EMC for those not keeping up)

iSCSI and vDS

I’m going to talk about virtual distributed switches (vDS) and how I set up my lab to get rid of traditional vSwitches. In my current lab of two ESXi hosts and some Iomega storage, I strive to make it look as “customer like” as possible. I don’t do the typical vCenter install that you click,click,click thru letting it install SQL Express and walk away. Nope, I do stuff like installing a full-blown SQL server and setting up vDS!

I wanted to separate out my VMkernel from my iSCSI. I wanted to put them on separate switches. vDS seemed logical for my setup as I could more easily play around with jumbo frames and all sorts of other cool stuff that’s come out with V5 like Netflow and port mirroring. Mind you, I’m probably not going to be dealing with that stuff on my iSCSI network but the option will be there..

Besides, vSwitches, as useful as they are, are kinda passé and I wanted to learn how to configure a vDS. So, I went searching around on the Interwebs and found a great article from Mike Graham at his blog “Mike’s Sysadmin Blog”. It showed how to set up iSCSI traffic to go over vDS. But it had a bunch of workarounds that required you to go into the command line on the ESX/ESXi server to “fix” things to work.

An additional article I highly recommend reading is from my friend Scott Lowe on Jumbo Frames and iSCSI+vDS. Scott’s article is based on vSphere V4 and like Mike Graham’s article on iSCSI and vDS, it lays out the required tweaking at the command line to make things work. In both cases they go into the requirements around modifying the VMkernel to start talking Jumbo Frames. According to my review of the vSphere V5 RC docs, I believe that’s no longer needed.

Well, in vSphere V5, you can do it all via the GUI! (and that means, of course, you can probably build a PowerCLI script that’ll do it!)

Step By Step

Start by creating a new vDS. We’ll call it “iSCSI dvSwitch”

Select the 5.0.0 version

ScreenShot132

Here I’ll set the number of dvUplink ports = 2. This means I’ll use 2 physical adapters PER HOST.

ScreenShot055

Now I’ll select what physical adapters I’ll use. In the example below, I’m using vmnic4 and vmnic5 on each of my Dell R610’s

ScreenShot099

So, now you’ll see the dvUplink’s ready to roll.

ScreenShot103

Just to clarify

dvUplink1 –

Host1/vmnic4

Host2/vmnic4

dvUplink2 –

Host1/vmnic5

Host2/vmnic5

ScreenShot103

The picture above will create default port groups. We’re going to create two of them. You’ll need to adjust the Teaming and Failover as follows.

From the docs:

If you are using iSCSI Multipathing, your VMkernel interface must be configured to have one active
adapter and no standby adapters. See the vSphere Storage documentation.

Setting things up as outlined below will ensure your iSCSI adapter is set up using a compliant portgroup policy.

Portgroup1 –

Active Uplink = dvUplink1

Unused Uplink = dvUplink2

Portgroup2 –

Active Uplink = dvUplink2

Unused Uplink = dvUplink1

ScreenShot105

When that’s done, the switch should look like this:

ScreenShot133

Now, in order to talk iSCSI to the iSCSI host, we need to bind a VMkernel to each port group. On each host, go to Configuration…Networking…vSphere Distributed Switch and down to the iSCSI-dvSwitch. Open “Manage Virtual Adapters…

ScreenShot137

Create a new Virtual Adapter with a VMkernel.(vmk1)

ScreenShot140

Assign IP address

ScreenShot110

Mapped to Portgroup1

ScreenShot108

Repeat all these steps for your other hosts.

Configuring iSCSI

If this was vSphere V4, you’d have to be doing some command line stuff to get the rest of this to work. Not in vSphere V5!

First step, we need an iSCSI Storage Adapter. For your first host, open Configuration…Storage Adapters and click on Add…

image

Now click the OK button to add the iSCSI Adapter. You see the following dialog box. Click OK

image

Ok, you now have your iSCSI adapter and it’s time to configure it. Click on Properties…

image

The dialog box opens and click on the Network Configuration tab.

image

Click the Add… button

You should now see something like the following:

image

Click on OK and you get this screen. Here’s where you’ll see the compliance portgroup policy check I pointed out earlier!

image

Now it’s time to set up some iSCSI connections. Click on the Dynamic Discovery tab and then on Add… I’ll add two connections to my two Iomega IX4-200R devices that I’ve preconfigured iSCSI disks on.

image

After I’ve added my connections and clicked on Close, I’ll be prompted to rescan for devices. Click on Yes.

image

In my case, you’ll see the two iSCSI disks show up in the Details for the iSCSI Storage Adapter

image

Now let’s go over to Storage and see the new datastores. You MAY have to click on Refresh to get a clean view.

image

Jumbo Frames

Lots has been talked about with regard to Jumbo Frames. Scott Lowe’s article touches on it for V4. Jason Boche has an awesome article on whether they actually help or not from a performance standpoint. I’ll leave that up to you as to whether it works or not.

As a bit of a recap, there’s two places in vSphere that Jumbo Frames need to be enabled.

  1. The VMkernel. Specifically, the NIC attached to the VMkernel being used for iSCSI traffic
  2. The vDS switch itself

Note that for Jumbo Frames to really work, you need to have everything from the vSphere level all the way thru the switches and the disk array supporting Jumbo Frames, otherwise it’ll either not work or performance will suffer.

VMkernel MTU Settings

Thankfully, in V5, this is all now settable via the GUI. Let’s start with the VMkernel. Go to Inventory…Hosts and Clusters…

Click on the host and then the Configuration Tab. Select Networking… and then Virtual Distributed Switch.

image

Now, for the iSCSI vDS, click on Manage Virtual Adapters… You’ll see the VMkernel, click on that and then Edit.

Under the General tab, you’ll see the NIC Settings and the MTU value. Set that to 9000.

Previously, this was a funky set of command line steps, all called out in Scott’s article. MUCH simpler now.

image

UPDATE!

Want to change this from PowerCLI? Well, you CAN!

[sourcecode language=”powershell” padlinenumbers=”true” wrap=”true”]
get-vmhost $host | get-vmhostnetworkadapter -vmkernel -name vmk1 |set-vmhostnetworkadapter -mtu 9000
[/sourcecode]

Virtual Distributed Switch MTU Settings

Now, let’s take a look at the vDS. Open the Inventory…Networking page. Select your vDS and click Edit Settings…

image

You’ll see the MTU value (Default 1500). Set that to 9000.

image

Wrap-up

Well, that’s it! You should now have iSCSI traffic moving across your vDS! Note: I haven’t tested jumbo frames and if they are truly working as advertised yet. I HAVE testing iSCSI over vDS and it works just fine. Just too much going on at the moment. If you can, please post some feedback.

So, with V5 of vSphere, VMware has continued to raise the bar in easy setup and configuration. They’ve now dropped the requirement to step into the command line of ESX(i) and run obtuse commands to get what seems like simple tasks to run. You no longer have to bind and set MTU values at the command line.

Please email me if I’m incorrect and I’ll be glad to fix this posting.

Thanks for reading!

mike

Provisioning a LOT of RSA SecurID iPhone (and other) Tokens using Powershell

So, you can tell from my previous blog post that I kinda dig Powershell and that I enjoy the occasional challenge. It helps me feel like I haven’t lost my technical chops. :)

This challenge started off one afternoon at lunch when I was talking with an RSA Sales Engineer. One of his customers was moving over, en mass, to iPhones and they wanted to provision a bunch of RSA SecurID iPhone tokens. Unfortunately, the iPhone Token Converter tool wasn’t really designed for that. It’s a single use command line. Here’s an example from the documentation:

The following command uses the -mobile option to convert a password-protected token file. The -mobile option is currently used with the SecurID for iPhone application, 1.2 or later.

C:\path_name\TokenConverter user2-passwordtoken.sdtid -p t0kenpw1 -mobile –o tokenfile.txt

The converted token data looks similar to the following:

com.rsa.securid://ctf?ctfData=200002068164720663136011170432774461076477164632456201
026172115044046062716712650

When you install the RSA SecurID iPhone token from the App Store, this funky URL is registered to be opened exclusively by the token. That then provisions the token with the user record and off you go.

But what if you want to provision 100 tokens? Or 1000 tokens? What a PITA that would that be! So, I thought “there’s gotta be a way to do this in Powershell”. And do it even better. Not only did I want to generate the token URL’s for all the users, but I wanted to generate a text file based on the username and the content being the token URL. THEN, I wanted to send out a custom email to each user with the token URL in it so they’d only have to download the app and click on the link! After all, it’s only a few extra lines of simple code, right? As you’ll see below, it really is just a few lines of actual code!

Challenges

To generate the URL for the token, you need a .SDTID file. This is the file that’s generated by RSA Authentication Manager when you marry a token record to a user. Thankfully, the format of this file is XML. Bonus! Powershell loves XML! Unfortunately, provisioning a ton of tokens from the Auth Man GUI isn’t straightforward. I know, I know, “Mike, we need Powershell cmdlets for Authentication Manager!!”

<Official Statement> Please provide that feedback to your RSA representative. <\Official Statement>

Create the files needed

Ok, so you’ve used whatever (supported) tools you needed to get a .SDTID file for every user. I recommend that each user be matched on a per file basis. Example: jsmith.stdid, mfoley.stdid, hsimpson.stdid, etc… Because you can link your Active Directory to your Authentication Manager, the names should be the same as your AD login name.

Note: Make sure all these files are all in one folder!

Now that you have all the files, you’ll need to get the Token Converter Tool we mentioned previously and the Powershell script below. In addition, I highly recommend getting the Quest AD cmdlets. Some BRILLIANT work here by your friends at Quest. Not only do they provide an amazing tool for working with Powershell and Active Directory, the cmdlets are also FREE! It’s almost a crime to download them. :)

Checklist

  1. Downloaded *.stdid files to an accessible location
  2. Downloaded the Token Converter Tool and put it in the same location as the script
  3. Downloaded the script
  4. IP/FQDN of your email server
  5. Downloaded and installed the Quest AD cmdlets

You’ll see in the script that all the Quest/email stuff is commented out. I tested it, but you’ll want to ensure it works for you before you start provisioning a ton of tokens.

Let’s step thru some of the code

Configure the IP address or FQDN of your email server by uncommenting and editing this variable

[sourcecode language=”powershell”]
# $smtpserver = 192.168.1.1

[/sourcecode]

Enable the Quest cmdlets and Connect to AD

[sourcecode language=”powershell”]
# Uncomment for using AD
#add-PSSnapin quest.activeroles.admanagement
#Connect-QADService

[/sourcecode]

Edit the variable that states where the .SDTID files are. Default is the same directory as the script.

[sourcecode language=”powershell”]
# $token_location is the directory that the sdtid files are located in.
# Current value is the same folder this script it.
$token_location = .
[/sourcecode]

Now, the script will read each file and parse information out of it

[sourcecode language=”powershell”]
$list_of_files = Get-ChildItem . -filter "$token_location\*.sdtid"
foreach ($file in $list_of_files)
{
Write-Host "Processing $file"
[/sourcecode]

Remember when I said the .SDTID file is XML at heart and that Powershell loves XML? When, let’s get the username associated with the token out of the file

[sourcecode language=”powershell” padlinenumbers=”true”]
Write-Host "Processing $file"
#Get the username out of the token file.
[xml]$list = get-content $file
$username = $list.TKNBatch.TKN.UserLogin
[/sourcecode]

So, why are we getting the username? Well, because with the AD cmdlets, we can use that to retrieve the email address!

[sourcecode language=”powershell”]
Write-Host "Generating Token for $username"
# Uncomment for using AD
#$AD_user = Get-QADUser $username
#$user_email = $AD_user.email
[/sourcecode]

Great, we’ve gathered up a bunch of info and now it’s time to run the token converter. But it’s an old-school CLI tool, right? How do I get the output that contains that funky URL? Easy.

[sourcecode language=”powershell” wraplines=”true”]
#Generate the token URL and output to a variable
$token_link = .\TokenConverter.exe $file -iphone
#Write out a file on a per-user basis with the iPhone Token URL inside it.
$filename = $username + "_Token.txt"
New-Item $filename -type file -Force -Value "URL for $username is $token_link"
#
[/sourcecode]

The output of the converter tool is now in the variable “$token_link”. Just to be safe, we’ll write out a text file with the contents of the URL.

Now, let’s send an email to the user with their custom URL for their token record.

[sourcecode language=”powershell” padlinenumbers=”true” wraplines=”true”]
# Uncomment for using AD and sending email.
#Send-MailMessage -SMTPserver $smtpserver -To $user_email -Subject "Your iPhone Token" -Body "Please click on the link provided $token_link to add the token to your iPhone"
}
[/sourcecode]

The closing “}” signifies that this is the end of the foreach loop we started with.

The script will chug thru each .SDTID file and generate the token URL and email to the user.

Wrap-up

The final script is here. I hope this was helpful. It shouldn’t take much to do the same thing for Android and other SecurID soft tokens. They all use the same Token Converter tool. I’ll leave it as an exercise for the reader to figure out how to make it work for them. RTFM :)

As always, read the EULA in the script and tread carefully. Most of all, I hope you enjoyed this as much as I did.

{UPDATE}
Line 43 below has a type due to the Syntax Highlighter I use. Replace with this line only changing the word “bracket” to the appropriate open and close brackets with no spaces.

bracket xml bracket $list = get-content $file

mike

The Script

[sourcecode language=”powershell”]
#
# Bulk iPhone Token creator
# Mike Foley, mfoley@rsa.com, 781-515-6391
# RSA, the Security Division of EMC
#——————————————————————————
# All information, statements, and descriptions herein are offered AS IS
# only and are provided for informational purposes only. EMC Corporation
# does not guarantee the performance of, or offer a warranty of any kind,
# whether express, implied, or statutory, regarding the information herein
# or the compatibility of the information herein with EMC Corporation software
# or hardware products or other products.
#——————————————————————————-
# Requirements:
# Windows Powershell – Run Windows Update and you’ll get it. Ships with Win7 and
# Win2008 by default
# Quest Active Directory cmdlets – Free download from
# http://www.quest.com/powershell/activeroles-server.aspx
#——————————————————————————-
# SMTP Server you can send email thru. If you are using Exchange and your CORP
# account, uncomment and point $smtpserver at a CORP Exchange server and the
# script will use your current AD credentials to automatically log in.
#
# $smtpserver = 192.168.1.1
#
# To take advantage of the Active Directory stuff, uncomment the code below and
# have a valid account that can browse the AD store
#
# Connect to any available domain controller with the credentials of the locally
# logged on user.
# See Help Connect-QADService -examples for more info
# Uncomment for using AD
#add-PSSnapin quest.activeroles.admanagement
#Connect-QADService
#
# $token_location is the directory that the sdtid files are located in.
# Current value is the same folder this script it.
$token_location = .
$list_of_files = Get-ChildItem . -filter "$token_location\*.sdtid"
foreach ($file in $list_of_files)
{
Write-Host "Processing $file"
#Get the username out of the token file.
[xml]$list = get-content $file
$username = $list.TKNBatch.TKN.UserLogin
Write-Host "Generating Token for $username"
# Uncomment for using AD
#$AD_user = Get-QADUser $username
#$user_email = $AD_user.email
#
#Generate the token URL and output to a variable
$token_link = .\TokenConverter.exe $file -iphone
#Write out a file on a per-user basis with the iPhone Token URL inside it.
$filename = $username + "_Token.txt"
New-Item $filename -type file -Force -Value "URL for $username is $token_link"
#
# Uncomment for using AD and sending email.
#Send-MailMessage -SMTPserver $smtpserver -To $user_email -Subject "Your iPhone Token" -Body "Please click on the link provided $token_link to add the token to your iPhone"
}
[/sourcecode]

How to provision 500 VM’s. Fast.

The Challenge

Back around March 2010, I was asked by Stephen Spellicy, who was on the vSpecialists technical marketing team, to help out on a project he was doing for EMCworld 2010. I drove up to the Nashua lab and sat down to help. Stephen told me about this new cool product coming out from EMC called VPLEX. He wanted to create 500 VM’s and he was going to show VPLEX vMotioning those systems from one datacenter to another. Oh, and Pat G. and Chad were doing to do it live on stage. Yea, no pressure.

So, the challenge to me was “Can you create a script that creates 500 VM’s?” Hell, that shouldn’t be too hard, even for a coding moron like myself so I responded with “I can write a Powershell script for that!”. And off I went…

Why Powershell?

You see, I suck at writing code. I’ll never be the guy who comes up with some seriously whacked algorithm that does amazing things with 5 bytes of code. Being a former IT guy, I think in tasks. This task was “Create 500 VM’s, each with a unique ID.”

Powershell was designed for that in mind. It takes the best of a number of IT Admin CLI’s. There’s bits of Bash, DCL and others mixed in there. It’s designed to get stuff done, with a minimum amount of hassle. Is it something I’m going to write an enterprise SaaS app in? Of course not. But for IT tasks like “Create 500 items using this template”, it’s damned near perfect.

The History of the Script

So, my first stab at this, before other requirements started coming in, was pretty simple. Ten or so lines of code. Read in from an Excel generated .CSV file the name of the VM’s and a foreach loop to create the VM’s asynchronously. But this presented a bunch of limitations. There was only one host and datastore defined. Naturally, that wasn’t going to cut it.

Version 2 took this a little further. Still the same limitations but it named the VM’s based on a count. e.g. DEMO_VM_1, DEMO_VM_2, etc… so I could dump the .CSV file and just use variables to control how many VM’s. But still, I needed to space out the VM’s being created across a number of hosts and a number of datastores. The script needed to be more adaptable.

Around this time, I started recruiting my friend Alan Renouf (@alanrenouf) to help me in this. I was rapidly reaching the need for a lifeline. Alan helped me with a few of the concepts and re-wrote some of the code to make it run better.

Version 3 took on a whole other look and feel. First, we created a unique template on each datastore. This way, when we were creating from template, we weren’t overtaxing the template datastore with IO requests. Next, we added a bunch of datastores and hosts and dumped them into arrays we could pull from.

Next, we added some code for generating randomness of the VM name so it wasn’t all done serially. We still used a standard prefix as an easy way to distinguish the VM’s from others.

Now, here’s where it got fun. I was reading a blog post from Luc Dekens (@lucd) on the Get-Task cmdlet and async tasks. I create a hash table of New-VM tasks This allows me to keep the pipeline of tasks going. As a task finishes, another task starts. It was VERY helpful.

Version 4 was mainly a cleanup and tweak. I used Luc’s code twice. Once for creating the VM’s and managing that process and second for starting the VM’s in a balanced fashion. Sure, I could have just said “Start-VM {list of VM’s}” but Luc’s code would start each one and monitor for success before starting another. This was much smoother.

The Result

The script would create 500 VM’s in a matter of minutes. It worked really well. And then Nick Weaver (@lynxbat) got a hold of it and tweaked it some more. (I’d still like a copy of that script Nick!) At EMCworld, I ran into Alan and Nick and told Alan that the code he helped with would be used for the big EMCworld Pat G/Chad demo. His response? “Crap, had I known that I would have done a better job!”

At the end of this, Stephen was happy and had christened the script “The Baby Maker” and called Alan and I “the proud parents”. I was ok with it up until the parents part. hahaha

 

So, I’m presenting my copy below. It’s quite functional and all in about 60 lines of actual code. If you need to create a BUNCH of VM’s, maybe for testing or benchmarking, this script will do it quite quickly. Use the code at your own risk. EMC and I are not responsible for you causing the end of mankind because you ran it. Oh, and batteries are not included.

#------------------------------------------------------------------------------
# 1st draft written by Mike Foley, @mikefoley, Virtualization Evangelist, RSA, The Security Division of EMC
# Contributions from Alan Renouf, @alanrenouf, EMC vSpecialist and PowerCLI guru
# Many thanks to those who's code we used, especially Luc Dekens, @LucD
#------------------------------------------------------------------------------
# All information, statements, and descriptions herein are offered AS IS
# only and are provided for informational purposes only. EMC Corporation
# does not guarantee the performance of, or offer a warranty of any kind,
# whether express, implied, or statutory, regarding the information herein
# or the compatibility of the information herein with EMC Corporation software
# or hardware products or other products.
#------------------------------------------------------------------------------
# 06-Apr-2010, Mike Foley, A simple Powershell/PowerCLI script to create a bunch of VM's. Written from lots of examples
# 20-Apr-2010, Alan Renouf, applied a different method of working out the numbers and re-wrote some of the code
# 21-Apr-2010, Alan Renouf, Fixed datastores which are used for deployment as per email from Mike.
#------------------------------------------------------------------------------
# You'll need to have the PowerCLI cmdlets installed. Get these from VMware.
# http://www.vmware.com/go/powercli

Add-PSSnapin -Name "VMware.VimAutomation.Core" -ErrorAction SilentlyContinue
#
#Things you can change
#------------------------------
$vchost = "10.5.103.185"
$num_vms_total = 4
$vm_prefix = "DEMO_VM_"
$Template_prefix = "tiny-ds-"
#-------------------------------
#Don't change below
$Template_Name = $vm_prefix + "*"

Connect-VIserver $vchost -user administrator -password emcworld

Write-Host "Collecting Template lists"
$Template_List = Get-Template $Template_Name | Select Name, @{N="Datastore";E={Get-VIObjectByVIView (Get-View ($_).DatastoreIdList)}} | Sort Name, Datastore

Write-Host "Collecting Datastore lists"
$Datastore_list = $Template_List | Select -Expand Datastore

Write-Host "Collecting Host lists"
$hosts = Get-VMHost | Sort Name

Write-Host "Collecting number of VMs per host"
$HostVMs = $hosts | Select Name, @{N="NumVM";E={@(($_ | Get-Vm ($vm_prefix + "*"))).Count}} | Sort NumVM, Name 

Write-Host "Collecting number of VMs per datastore"
$DSVMs = $Datastore_list | Select name, @{N="NumVM";E={@($_ | Get-VM ($vm_prefix + "*")).Count}} | Sort NumVM, Name

#Setup for Get-Random in the loop below
$min = [char]'a'
$max = [char]'z'
$alpha = [char[]]($min..$max)
$ofs = ''
$taskTab = @{}
$vm_count = 0

While ($vm_count -lt $num_vms_total){
    Write-Host "Finding host with least amount of $vm_prefix VMs on it"
    $LeastHost = $HostVMs | Sort NumVM | Select -First 1
    Write-Host "Finding datastore with least amount of $vm_prefix VMs on it"
    $LeastDatastore = $DSVMs | Sort NumVM | Select -First 1
    $ran_text = [string]( $alpha | Get-Random -Count 5 )
    $VM_Name = $vm_prefix + $ran_text + $vm_count
    $Template = ($Template_List | Where {$_.Datastore.Name -eq $LeastDatastore.Name}).Name
    Write "Create a virtual machine called $VM_Name on $($LeastHost.Name) using a template called $Template onto a datastore called $($LeastDatastore.Name)"
    $taskTab[(New-VM -Name $VM_Name -Template $template -VMHost (Get-VMhost $LeastHost.Name) -Datastore (Get-Datastore $LeastDatastore.Name) -DiskStorageFormat Thin -RunAsync ).Id] = $VM_Name
    $DSVMs | Where { $_.Name -eq $LeastDatastore.Name } | Foreach { $_.NumVM++ }
    $HostVMs | Where { $_.Name -eq $LeastHost.Name } | Foreach { $_.NumVM++ }
    $vm_count ++
}

Write-Host "-----------------------"
Write-Host "VM Deployment completed"
Write-Host "-----------------------"

Write-Host "-----------------------"
Write-Host "Starting VM's"
Write-Host "-----------------------"


#
## Start each VM that is completed
$runningTasks = $taskTab.Count
while($runningTasks -gt 0){
    Get-Task | % {
        if($taskTab.ContainsKey($_.Id) -and $_.State -eq "Success"){
            $xx = Get-VM $taskTab[$_.Id] 
           Write-Host "Starting VM " $xx.Name
            Get-VM $taskTab[$_.Id] | Start-VM 
            $taskTab.Remove($_.Id)
            $runningTasks--
        }
        elseif($taskTab.ContainsKey($_.Id) -and $_.State -eq "Error"){
            $taskTab.Remove($_.Id)
            $runningTasks--
        }
    }
    Start-Sleep -Seconds 15
}

#
#Disconnect-VIserver -server $vchost -confirm:$false
#
#
#
#foreach($Name in $newVmList){
#    $taskTab[(New-VM -VM (Get-VM $modelVm) -Name $Name -VMHost (Get-VMHost -Name $esxName) -RunAsync).Id] = $Name
#}

Cleaning up

Ok, you’ve just created 1000 VM’s and you’re thinking “Dammit Foley! How do I get rid of all of these VM’s quickly before my boss finds out!” Easy Chief, I’ve got you covered. Below is the Remove-VM’s script that uses Luc’s code, again, to troll thru the VM’s, create a hash table and delete them.

 

#
# 21-Apr-2010, Mike Foley, A simple Powershell/PowerCLI script to delete a bunch of VM's. Written from lots of examples
#------------------------------------------------------------------------------
# 1st draft written by Mike Foley, @mikefoley, Virtualization Evangelist, RSA, The Security Division of EMC
# Contributions from Alan Renouf, @alanrenouf, EMC vSpecialist and PowerCLI guru
# Many thanks to those who's code we used, especially Luc Dekens, @LucD
#------------------------------------------------------------------------------
# All information, statements, and descriptions herein are offered AS IS
# only and are provided for informational purposes only. EMC Corporation
# does not guarantee the performance of, or offer a warranty of any kind,
# whether express, implied, or statutory, regarding the information herein
# or the compatibility of the information herein with EMC Corporation software
# or hardware products or other products.
#------------------------------------------------------------------------------
#
# You'll need to have the PowerCLI cmdlets installed. Get these from VMware.
# http://www.vmware.com/go/powercli
#
#Things to change
$vchost = "10.5.103.185"
$vm_prefix = "DEMO_VM_"
$VM_Name = $vm_prefix + "*"
#
#
Add-PSSnapin -Name "VMware.VimAutomation.Core" -ErrorAction SilentlyContinue
#
#
Connect-VIserver $vchost -user administrator -password emcworld
#
$list = Get-VM $VM_Name

foreach ($vm in $list){
    If ($vm.powerstate -eq "PoweredOff") {
    Write-Host "Removing PoweredOff VM " $vm
    Remove-VM -DeleteFromDisk -vm $vm -RunAsync -confirm:$false }
    ElseIf ($vm.powerstate -eq "PoweredOn"){
    Write-Host "Creating Hash Table and Stopping VM " $vm
    $taskTab[(Stop-VM  -vm $vm -RunAsync -confirm:$false).Id] = $vm}
    }



# Start each VM that is completed
$runningTasks = $taskTab.Count
while($runningTasks -gt 0){
    Get-Task | % {
        if($taskTab.ContainsKey($_.Id) -and $_.State -eq "Success"){
            $xx = Get-VM $taskTab[$_.Id] 
            Write-Host "Removing VM from Hash Table " $xx.Name
            Get-VM $taskTab[$_.Id] | Remove-VM -DeleteFromDisk -RunAsync -confirm:$false 
            $taskTab.Remove($_.Id)
            $runningTasks--
        }
        elseif($taskTab.ContainsKey($_.Id) -and $_.State -eq "Error"){
            $taskTab.Remove($_.Id)
            $runningTasks--
        }
    }
    Start-Sleep -Seconds 15
}

 

Enjoy!

mike