Apples and Oranges – Always More than one way

Many moons ago, I started modifying a script called “Healthcheck” written by Richard Giles (at least the source I found).

It was quite handy and gathered lots of useful tidbits of information. But, as our VMware environment grew, the script slowly began to take longer each time. We now have well over 250 virtual machines.

One “child” script I ended up with you’ll see next. This basically uses the same method to mine the information as did the Heathcheck PowerShell script. Against over 250 virtual machines, it was taking up to 45 minutest to complete at times.

Add-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue

$VMReportFile = Read-Host "Enter CSV Filename UNC PATH (i.e., \\machine\share\filename.csv)"
$VMInfoReport = @()
$VCServer = Connect-VIServer "vcenter"

Get-VM | ForEach-Object {
$vm = Get-View $_.ID
$row = "" | Select VMname, Host, Description
$row.VMname = $vm.Name
$row.Host = Get-VMHost -vm $vm.name
$row.Description = $vm.Config.Annotation
$VMInfoReport += $row
}

$VMInfoReport | sort -property VMname | Export-Csv $VMDataStoreFile -NoTypeInformation

# ---------------------------------------------------------------------------

# Disconnected from vCenter
Disconnect-VIServer $VCServer -Confirm:$False

trap{
Write-Host "ERROR: script execution was terminated.`n" $_.Exception.Message
# Disconnected from vCenter
Disconnect-VIServer $VCServer -Confirm:$False
break
}

Now, the weekness in this approach is having to do a get-view then query against vcenter to find the virtual machine’s host:

Get-VMHost -vm $vm.name

When I was trying to break the script down to understand this better, I used measure-task against various portions of the script. The culprit was always get get-vmhost:

measure-command {Get-VMHost -vm $vm.name}

This produced times ranging from 10-18 seconds.

I quickly realized the error of my ways in re-using the Healthcheck script. Since I only needed three items of information, I didn’t need to use get-view at all. I only needed to use get-vm.

Here is the script I ended up with shortly after:

Add-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue

$VMReportFile = Read-Host "Enter CSV Filename UNC PATH (i.e., \\machine\share\filename.csv)"
$VCServer = Connect-VIServer "vcenter"
$VMInfoReport = @()

$VMs = Get-VM | Out-Null

foreach ($item in $VMs){
$row = "" | Select VMname, Host, Description
$row.VMname = $item.Name
$row.Host = $item.Host
$row.Description = $item.Description
$VMInfoReport += $row
}

$VMInfoReport | sort -property VMname | Export-Csv $VMReportFile -NoTypeInformation

# ---------------------------------------------------------------------------

# Disconnected from vCenter
Disconnect-VIServer $VCServer -Confirm:$False

trap{
Write-Host "ERROR: script execution was terminated.`n" $_.Exception.Message
# Disconnected from vCenter
Disconnect-VIServer $VCServer -Confirm:$False
break
}

Now the script runs and I have my data in less than a minute.

Advertisements

Power Me On – Simple VMware PowerShell Script

I’ve got PowerShell open almost all the time.  But I don’t always have the vSphere client open.

At my company, we are also encouraging others to use PowerShell.  One quick idea I came up with is a simple script with a bit of simple error-handling that will allow anyone with the correct permissions to power on their VM when it’s in a powered-off state.

When we get a request to power on a machine, it’s just easy to run the script, type in the VM name when prompted, and voila!  Houston, we have power!

A similar script can also be written to power off, shut down, or restart. However, one might think “why go through all that trouble just to shut down a VM?  Why not just use

Shutdown-VmGuest "vmname"

Well, one reason would be if it’s a “one off” task.  It’s more convenient to do in a saved script.  It also allows for some error handling.  For instance, if a shut down script was being shared with a help desk staff you could also add scripting to confirm the VM name prior to shut down.

At any rate, here’s the power on script:

Add-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue

# Variables
$VCServer = "vcenter.myord.local"
$datacenter = "DC"

$PowerOnVM = Read-Host "Virtual Machine name you wish to power on?"
# Connect to vCenter
Connect-VIServer $VCServer | Out-Null

# Make sure VM exists
$VM = Get-VM | where-object {$_.Name -eq $PowerOnVM}

# If no value returned, tell user they provided wrong name
if ($VM -eq $null){
Write-Warning "$PowerOnVM is an invalid VM name"
break
}

# If it's already powered on, tell the user and abort
if ($VM.PowerState -eq "PoweredOn"){
Write-Host "$PowerOnVM is already powered on"
# Disconnected from vCenter
Disconnect-VIServer -Confirm:$False
break
}

# Beam me up Scotty, power on
(Get-View $VM.Id).PowerOnVM($_.Runtime.Host)

# Always Disconnected from vCenter so all connections are
#closed from your machine at the end of your script
Disconnect-VIServer -Confirm:$False

trap{
Write-Host "ERROR: script execution was terminated.`n" $_.Exception.Message
# Disconnected from vCenter
Disconnect-VIServer -Confirm:$False
break
}

PowerShell Commenting – Part 2

In an earlier post, I presented my opinion on commenting in scripts.  This post will supplement that opinion with what I think should be an defacto standard for all system administrators.

Where I work, we are using a commenting standard set up by our senior Microsoft engineer.  This blog post is not about that standard but one I have come to prefer recently.

Let me emphasize the use of standards; if you have a developed standard, by all means follow that standard.  Standards are put in place for specific reasons.  Unless there’s a good reason to deviate from that standard, don’t.  And, make sure to thoroughly discuss and plan changes to standards in your organization.

So, now, on to my “personal” preference on commenting in scripts.

I have slowly developed a personal liking to the comment block.  There are several reasons for this.

1) A comment block is just so much cleaner and “elegant”.  Using a nice editor such as PowerShell Plus, you can expand or collapse the comment block.  It is so much easier to “tuck” it out of the way when you don’t need to see the comments.  It’s just as easy to expand it when you need to read and/or add additional information to the comment block.  Typically, once you’ve provided that information in your own scripts, you rarely need to go back to it unless editing is required.

2) With PowerShell 2.0, it is now very important to provide version information and any requirements in the comments.  I prefer to comment any saved scripts I write.  But, if you are one who is inclined not to do so, it is strongly encouraged that you provide comments in any scripts you share.  Version information, snapins, modules, elevation of permissions, and other items can be added.  In fact, Thomas Lee has a very good post on this information on his blog:  More on PowerShell’s #Requires Statement.

3) This integrates well with what many are calling “inline help.”  Again, I have to credit Thomas Lee for some very good blog posts on this subject which is what helped me define this new-found preference.  These posts are:

PowerShell CTP3 AutoHelp

Get-AutoHelp.ps1

Great WOL script

I have been applying XP SP3 and installing Windows Management framework in the computer lab at my daughter’s school. I have been attempting to do all of it via remote desktop. It doesn’t always work out. I knew that WOL had been enabled for all those PC’s. So, I decided I was going to write a WOL script last week.

A few seconds of using Google netted me a cool script by Cosmin Dumitru on poshcode.org.

http://poshcode.org/672

This is a fantastic script. All you need a CSV file with two columns. One labeled “computername” and the other “mac”. Save that file off as a CSV file named “workstations.txt” and store it in the same folder you save this WOL script. Works like a charm!