Quickly power on virtual machines with PowerCLI Get-View

I recently had a need to power on a lot of virtual machines in a specific order. I was given several text files each numbered with a startup sequence. At a specific time I would be given a number and need to power on all of the virtual machines associated with that startup sequence number. Several minutes later I would be given another number and need to power on all of those virtual machines. Using Get-VM and Start-VM really wasn’t an option… even with -RunAsync that option was kind of slow.

The option I finally settled on involved using Get-View to return a list of all virtual machines; I would then use Where-Object to find the specific VM and finally invoke the PowerOnVM_Task to start the VM. During some testing, I realized this was almost too fast. Nearly all of the power on tasks would queue up in vCenter and all the VMs would power on in very large batches. To keep things somewhat controlled, I added a very short .5 second delay between virtual machine power on tasks.

[cc lang=”Powershell”]
$serverList = Read-Host “Which list would you like to power on? ”
$view = Get-View -ViewType ‘virtualmachine’ -Property Name

$taskTracker = @()
Get-Content “$serverListList.txt” | %{
$vmName = $_
Write-Host “Now powering on VM: $vmName … ” -nonewline
$taskTracker += ($view | ?{$_.name -eq “$vmName” }).PowerOnVM_Task($null)
Start-Sleep -Milliseconds 500
Write-Host “done!”
}
“Submitted $($taskTracker.Count) power on requests”
[/cc]

2013/10/20 Update: Just to clarify, I had files named 1list.txt, 2list.txt, 3list.txt and so on, each containing a virtual machine name listed one per line of the file. When the Read-Host cmdlet asked ‘Which list would you like to power on?’ I just answered 1, 2 or 3. The script automatically appends the list.txt to the file name on the Get-Content line.

This script can potentially throw some errors that are not accounted for in code, but weren’t a show stopper in my situation. First of all, this script does not account for vApps or scenarios where multiple virtual machines have identical names. vApps typically have their own startup order defined within the app. This process will turn on member VMs but may or may not be in the correct order. Another problem would be if you have two virtual machines with the same name, such as “UI VM”. This script will not turn on either (however it could be modified slightly to do so). The last issue I’m aware of is that this process will attempt to turn on any virtual machine in the list without first checking to see if the virtual machine is currently running. If a VM was powered on before my script reached it, the error “The operation is not allowed in the current state” was logged in vCenter and in the script. In my situation this was acceptable.

Posted in Scripting, Virtualization | 2 Comments

Do you have any way of getting server name from the attached list of IPs?

Every now and then I get a simple script idea in my email, like this one from a couple weeks ago:

Do you have any way of getting server name from the attached list of IPs?

This is a pretty simple request, and there are probably thousands of possible solutions, but I threw together a quick function that accepts an IP Address as a string and returns the IP address and a host name… like this:
[cc lang=”powershell”]
Function Get-HostName ([string]$ipAddress) {
New-Object psobject -Property @{
IPAddress = $ipAddress
HostName = try { [system.net.dns]::GetHostByAddress($ipAddress).HostName } catch { “UNKNOWN” }
}
}
[/cc]

That’s almost a solution… the only thing remaining would be to read in the text file, call the function for each line and then export the results. That can all be done in one line of code, but I put in some line breaks to make it easier to read:
[cc lang=”powershell”]
Get-Content ipList.txt |
%{ Get-HostName $_ } |
Export-Csv MyIPsExport.csv -NoTypeInformation
[/cc]

Posted in Scripting | 1 Comment

When are Windows patches happening?

As most people know, Microsoft releases patches on the second Tuesday of the month. In some organizations these patches are deployed to development, test and QA systems within a couple of days of the release. However, production systems can’t be patched until the next maintenance window. Assuming this patch window is on a Saturday, we need to find the first Saturday after the second Tuesday. When looking at a calendar this is pretty simple for most people to figure out. However, when you need a whole years worth it takes a few minutes to calculate. What we need is some code to look these up for us…like this function:

[cc lang=”Powershell”]
Function Get-WsusSaturday {
param([datetime]$date=(Get-Date) )
$numberOfTuesdays=0

1..([datetime]::DaysInMonth( $date.year , $date.month )) | %{
$thisDate = Get-Date “$($date.month)/$($_)/$($date.year)”
if ([string]$thisDate.DayOfWeek -eq ‘Tuesday’) {
$numberOfTuesdays++
if ($numberOfTuesdays -eq 2) {
$thisDate.AddDays(4).ToLongDateString()
}
}
}
}
[/cc]
Line 2: accept the date as a parameter and cast it to a date/time value, defaulting to today’s date if nothing is provided
Line 3: max sure we don’t think its Tuesday already
Line 5: starting on the first of each month, loop through the max number of days in the month
Line 8: if the date is Tuesday, add one to the counter
Line 9: once we find the second Tuesday
Line 10: add 4 more days to find the following Saturday and return the date text

You can take this function and do something creative, like find the next 5 years worth of patch Saturdays.
[cc lang=”powershell”]
13..18 | %{
$year = $_
1..12 | %{ Get-WsusSaturday “$_/1/$year” }
}
[/cc]

Posted in Scripting | Leave a comment

Hashtables: Item has already been added

In my previous two posts about hashtables I provided examples for creating a hashtable, returning a specific value and a description around performance. This post will focus on the errors you should expect if you start using a hashtable.

The most common exception I see happens when the data I’m storing in the hashtable is not unique. For example, in the first post in the series we created a simple hashtable from a list of HTML colors. If my input list had the color ‘red’ listed on two different lines, I would have seen an error similar to this:

Add : Exception calling “Add” with “2” argument(s): “Item has already been added. Key in dictionary: ‘Red’ Key being
added: ‘Red'”
At line:1 char:17
+ $colorCodeHT.Add <<<< ('Red','123456') + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : DotNetMethodException

This is an easy error message to generate if you want to see the actual error. Follow the examples in the first post and then try and re-add the color red using the following line:
[cc lang=”powershell”]
$colorCodeHT.Add(‘Red’,’123456′)
[/cc]

The hashtable object includes a .Contains method, which can be used in an if statement to prevent this exception from happening:
[cc lang=”powershell”]if ($colorCodeHT.Contains(‘Red’)) { “Color ‘red’ has already been added” } else { $colorCodeHT.Add(‘Red’,’123456′) }[/cc]

This statement checks for the presence of a ‘Red’ item and only attempts to add if a value does not already exist.

Posted in Scripting | Leave a comment

Hashtables: Adding, Updating and Removing Items

To help describe these concepts, I have listed a few examples based on a CSV file containing HTML color codes.

For purposes of sample data, create an array object of colors and HTML color codes.
[cc lang=”powershell”]$colorCodes = Import-Csv ColorCodes.csv[/cc]

Define a hashtable object:
[cc lang=”powershell”]$colorCodeHT = @{}[/cc]

Examples for adding to a hashtable:
[cc lang=”powershell”]
# For the old vbscripter (this is the method I use)
# $colorCodeHT.Add(‘key’,’value’)
$colorCodes | %{$colorCodeHT.Add($_.ColorName, $_.Code)}

# For the person who likes equal signs
# $colorCodeHT[‘key’] = ‘Value’
$colorCodes | %{$colorCodeHT[$_.ColorName] = $_.Code}
[/cc]

Examples for updating existing entries
[cc lang=”powershell”]
# Using square brackets, just like the above ‘add’ example
$colorCodeHT[‘Red’] = ‘#123456’
[/cc]

Examples for removing from a hashtable:
[cc lang=”Powershell”]
# Remove a single item by key
$colorCodeHT.Remove(‘Red’)

# Remove all of the entries from the hashtable:
$colorCodeHT.Clear()
[/cc]

Posted in Scripting | Leave a comment