Threaded Report Generator: VMs without a vmxnet3 vmnic

Yesterday I worked on a nice-to-have script for our Team. Since I had some time on my hands, I decided to give it a take from a different angle and make it threaded. I was fiddling around and googling like crazy, but eventually after several failed attempts and debugging sessions it paid off. I did a huge step in scripting for myself, and I’d like to present the script to you! Threading is something I wanted to learn for a long time, so I am very happy I am able to share this piece of code.

What the script basically does is grab a list of vCenters either via an array (the line can be modified to get it via get-content instead), and then creates a thread (aka a Background Job) for each of them, using the ScriptBlock that is defined in $getnics variable. You can take a look at it and it somewhat closely resembles a function. With one exception – the ScriptBlock for this kind of job (having pristine CSV values) must be completely silent except the last step – returning the $csv value.

When all jobs finish via Get-Job | Wait-Job, all the variables are aggregated into one master variable $csv with Receive-Job commandlet. This retrieves the output contents of the job but also marks them in a way that you couldn’t retrieve these contents again (the variable will be blank), so extra caution is needed there. In the end it all gets outputted to C:\temp\ as a CSV with forced semicolon separator.

In the end you are shown the total time in seconds the script took to run – in our environment of roughly 4500 VMs across all vCenters, it took about 1s per VM non-threaded. The threaded run was completed in ~700 seconds, which is a nice speed boost 🙂 The sample of how the report looks is below:

Sample Report

A report generated with columns for vCenter, its VM, the NIC Type and Guest OS.

 

Write-Host "Threaded vmnic type Gatherer " -ForeGroundColor Cyan
$startedtime = Get-Date

# get date to present to the .csv file
$date = Get-Date -format ddMMyy-HHmm

# Initialize CSV Here
$csv = @()
$csv += "sep=;"
$csv += "vCenter;VM;NIC Type;Guest OS"

# List of vCenters where to gather data from, can be replaced with get-content.
$vcenterlist = @("vcenter1","vcenter2")

# Initialize ScriptBlock to be used in Threads
$getnics= {	# The curly bracket is needed to initiate ScriptBlock
	Param([String]$vc)  # A vCenter will be an input parameter
	Process {	# Start the ScriptBlock's work here:
	$WarningPreference = "SilentlyContinue" # Disable warnings
	[array]$csv = $null # Initialize empty CSV Array

	# Since PowerCLI SnapIn isn't present in Threading, we need to load it
	add-pssnapin VMware.VimAutomation.Core -ea 0 | out-null

	Connect-VIServer $vc -wa 0 | out-null # Connect to vCenter, Silently

	$AllVMs = get-vm # Gather Virtual Machines...

		# Do a ForEach Object (%) on each VM to find out wich VMnic they have
		$AllVMs | % {

		$ThisVM = $_
		$vmnic = (Get-NetworkAdapter -VM $ThisVM).Type

		# No vmxnet3 NICs, no NULL values and no dummy SMVI machines.
	If ($vmnic -ne 'vmxnet3' -and $vmnic -ne $null) # If vmnic isn't vmxnet3 and isn't null, then:
		{
		$guestos = $ThisVM.Guest.OSFullName
		$csv += "$vc;$ThisVM;$vmnic;$guestos"
		}

		}
		return ,$csv

	# Disconnect from vCenter
	Disconnect-VIServer $vc -wa 0 -confirm:$false | out-null
	}
}

# Start threads and impose a wait time so the CPU on the terminal doesn't go crazy.
forEach ($vc in $vcenterlist) {

Write-Host "Starting Thread for" $vc -NoNewLine
Start-Job -Scriptblock $getnics -ArgumentList $vc | out-null
Write-Host "...Done!" -ForegroundColor "Green"
Start-Sleep -s 15

}

Write-Host "All threads started! Waiting for them to finish." -Foregroundcolor Green

# List jobs and wait until they are all completed
Get-Job | Wait-Job 

# Gather data from Threads by aggregating each job into a master CSV variable.
Write-Host "Gathering data from the threads..."
$jobs = Get-Job | ? {$_.State -eq "Completed"}
ForEach ($job in $jobs) {
	$csv += Receive-job $job
}

# Write CSV File
$csvpath = "C:\temp\vmnicreport_$date.csv"
Write-Host "Writing CSV file to $csvpath"
$csv | Out-File $csvpath

# Final stats
$endedtime = Get-Date
$timetook = ($endedtime - $startedtime).TotalSeconds

# Cleanup
Get-Job | Remove-Job

Write-Host "Finished in" $timetook "seconds!" -ForegroundColor Green

I hope you will find this script useful one day when deciding which VMs to upgrade – but don’t forget to update VMware tools first before you get into it, so your VM has sustained connectivity after a reboot.

Advertisements

Share your thoughts

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s