Archive

Author Archive

Powershell Power! (Part the First)

February 17th, 2009 Mark A. Weaver No comments
Rating 3.00 out of 5

This will (hopefully) be the first of several ‘tutorials’ on Powershell.

Many of you have probably seen code in the forums or tutorials online that show some exerpts of code that are just CRAZY!  Many containing aliases like “%” and “?” and lots of braces and parentheses of all shapes and sizes.

Well, one of the things I love about Powershell is that you can do some VERY powerful, yet hard-to-read things at the command line.  While this may seem super and efficient for someone who knows Powershell, it SUCKS if you are trying to learn the language.

When I was trying to pick it up, this is all you could really find and it wasn’t until I found (what I believe to be the Powershell BIBLE) Windows PowerShell in Action by Bruce Payette.

In my mind there are ideally two different styles to Powershell(ing).

  • The free-form, Wild-Wild-West,  I-need-to-pound-this-out  command line style
  • The structured, methodical, EXPLICIT scripting style

From a practical sense, though, I think most people end up somewhere in the middle.  What absolutely drives me bonkers is obscure-one-liners that veteran Powershell scripters spew to  the newbie scripters asking relatively simple questions like:

“How  do I get a list of all files in a directory that have been modified in the last 3 weeks?”

One may be inclined to say “Oh, that’s easy!  Here it is…”

gci |sort| %{if ($_.LastWriteTime -GT (get-date).Adddays(-21)) `
{write-host $_.name "--"  $_.LastWriteTime -foreground Red}}

But for someone unfamiliar with Powershell, it looks like a bunch of gibberish.  Now something like THIS may be more helpful for them:

$AllFiles = Get-ChildItem | Sort-Object
$Now = Get-Date
$CutoffDate = $Now.AddDays(-21)
Foreach ($File in $AllFiles) {
     If ($File.LastWriteTime -gt $CutoffDate)
     {
      Write-Host $File.Name "--" $File.LastWriteTime -Foreground Red
      }
  }

Okay, if someone is asking this question, they are certainly new to the language and so an obscure response will probably only confuse them and, hopefully, not taint their desire to learn this robust and relatively simple tool.

ANYWAY… sorry about that half rant/half informational bit…Let’s talk a little bit about Powershell…

What *IS* Powershell?

Well the quick-and-dirty is that it is a “new” scripting language and command shell geared for IT administrators with a focus on simplicity, power, and automation.

The “official” description can be found here: http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx

Anyway, now that you have an idea of what Powershell is, we will take a peak at some of the easy stuff you can do with it.  I will probably start with some of the fundamentals of scripting and move forward from that.

That’s all for now, but I will write more shortly.  I still haven’t figured out what format I want to use, but we will figure it out together.

Thanks for reading, sorry for the mild rant, and happy shelling!

– Mark

Get-HACapacity

February 6th, 2009 Mark A. Weaver No comments
Rating 3.00 out of 5

This script will calculate the HighAvailability capacity of a VMware ESX Cluster.

### Written by Mark A. Weaver
##  Date: 7/27/2008
##  Version: 1.0
##  Website: www.vmweaver.com
##
##  Call this function and pass in -ServerName  -ClusterName
##  Output should be an object containing the information
##
##  Feel free to modify as needed to suit your needs, but please keep this header
##
##  Thanks  -- Mark
 
function Get-HACapacity(
[string]$ServerName,
[string]$ClusterName)
{
		if (($ServerName -ne "") -and ($ClusterName -ne ""))
	{
		# These booleans tell me if I am using the VMware default memory and cpu reservations for the cluster.
			$DASMemDefault = $True
			$DASCPUDefault = $True
 
		# The following numbers are derived from VMware published numbers for memory overhead.
		# I have dropped them into arrays using the number of vCPUs as an index to get the correct constant.
		# This is why you will notice only [1], [2], and [4] have non-zero values
		# These constants are used later on when calculating Memory Reserve.
			$MemConst32 = 0, 3.262, 5.769059, 0, 6.77933
			$MemConst64 = 0, 3.2678, 5.79251, 0, 6.82622
			$MemBase32 = 0, 87.56, 108.73, 0, 146.75
			$MemBase64 = 0, 107.54, 146.41, 0, 219.82
 
		# Initialize some Variables
			$MaxMemRes = 0
			$MacNumCPU = 0
			$MaxCPUResVM = ""
			$VMCount = 0
 
		# define default memory and cpu reservation
			$DASMinMHz = 256
			$DASMinMemory = 256
 
			$viServerName = $ServerName
			$viClusterName = $ClusterName
 
		# Connect to the VirtualCenter Server and get some info
			$viServer = Connect-VIServer $viServerName
			$viCluster = get-cluster $viClusterName
			$viHosts = get-vmhost -location $viCluster
			$viClusterV = get-view $viCluster.ID
 
		# Get the "Resources" Resource Pool from the cluster.
		# This gives us the Reservation Pools for Memory and CPU
			$viResGroup = Get-ResourcePool -Name "Resources" -Location $viCluster
			$viCPURes = $viResGroup.CpuReservationMHz
			$viMemRes = $viResGroup.MemReservationMB
			$viHostCount = $viClusterV.Summary.NumHosts
 
		# Get HA cluster configuration information
			$viHostFailures = $viClusterV.Configuration.DasConfig.FailoverLevel
 
		# Get a list of options that may be configured at the clusters level
		# We are looking for whether or not the default memory and cpu
		#  reservations have been overridden
			$viDASOptions = $viClusterV.Configuration.DASConfig.Option
			$viVMs = get-vm -Location $viCluster
 
		# Is Adminisssion Control enabled on the cluster?
			$viClusterControl = $viClusterV.Configuration.DASConfig.AdmissionControlEnabled	
 
		# See if das.vmMemoryMinMB key is defined and grab its value
		# See if das.vmCpuMinMHZ key is defined and grab its value
			if ($viDASoptions.Count -ne 0)
			{
				foreach ($viDASOption in $viDASOptions)
				{
					if ($viDASOption.Key -eq "das.vmMemoryMinMB")
					{
						$DASMemDefault = $False
					$DASMinMemory = $viDASOption.Value }
 
					if ($viDASOption.Key -eq "das.vmCpuMinMHz")
					{
						$DASCPUDefault = $False
					$DASMinMHz = $viDASOption.Value }
				}
		}
 
		# Let's go through every VM and see what the maximum CPU and Memory reservation is.
		# We will also get a count of powered on VMs.
		# When we hit a maximum reservation, save the machine name that set that maximum
			foreach ($viVM in $viVMs)
			{
				$NumCPU = $viVm.NumCPU
				$VMMem = $viVm.MemoryMB
				$MemRes = 0
 
				if ($viVM.PowerState -eq "PoweredOn")
				{
					$VMCount += 1
			}
 
			# Get the VM-view and determine if the current guest CPU or memory reservations configured
			$vmView = get-view $viVM.ID
			$vmViewCPURes = $vmView.ResourceConfig.CpuAllocation.Reservation
			$vmViewMemRes = $vmView.ResourceConfig.MemoryAllocation.Reservation
 
			# If no reservations are set at the VM level, calculate the memory reservation.
			if ($vmViewMemRes -eq 0)
			{
				if ($VMMem -le 256)
				{
					$MemRes = $MemConst64[$NumCpu] + $MemBase64[$NumCPU]
				}
				else
				{
					if ((($viVM.Guest.OSFullName | Select-String "64-bit").Matches.Count) -ge 1)
					{
						$MemRes = ($VMMem / 256) * $MemConst64[$NumCPU] + $MemBase64[$NumCPU]
					}
					else
					{
						$MemRes = ($VMMem / 256) * $MemConst32[$NumCPU] + $MemBase32[$NumCPU]
					}
				}
 
				$MemRes += $DASMinMemory
			}																			
 
			else
			{
				$MemRes = $vmViewMemRes 									
 
			}
 
			#Figure out if the current VM holds the highest reservation so far
 
				if ($vmViewCPURes -gt $DASMinMHz)
				{
					$DASMinMHz = $vmViewCPURes
					$MaxCPUResVM = $viVM.Name
				}			
 
				if ($MemRes -gt $MaxMemRes)
				{
					$MaxMemRes = $MemRes
					$MaxMemResVM = $viVM.Name
				}
 
				if ($NumCPU -gt $MaxNumCPU)
				{
					$MaxNumCPU = $NumCPU
					$MaxCPUNumVM = $viVM.Name
				}
 
			}
 
			if ($MaxCPUResVM -eq "") { $MaxCPUResVM = $MaxCPUNumVM }			
 
		$MaxCPURes = $MaxNumCPU * $DASMinMHz
 
		# Calculate the VM Capacity for the cluster based on memory and cpu reservations.
			$ClusterVMCapacityMEM = [Math]::Truncate(((($viMemRes / $MaxMemRes) * ( $viHostCount - $viHostFailures )) / $viHostCount))
			$ClusterVMCapacityCPU = [Math]::Truncate(((($viCPURes / $MaxCPURes) * ( $viHostCount - $viHostFailures )) / $viHostCount))
 
			if ($ClusterVMCapacityMEM -lt $ClusterVMCapacityCPU)
			{
				$ClusterVMCapacity = $ClusterVMCapacityMEM
			}
			else
			{
				$ClusterVMCapacity = $ClusterVMCapacityCPU
		}
 
		# Create an object to return
			$CPUObj = New-Object System.Object
			$CPUObj | Add-Member -type NoteProperty -name ClusterCPURes -value $viCPURes
			$CPUObj | Add-Member -type NoteProperty -name DefaultCPURes -value $DASCPUDefault
			$CPUObj | Add-Member -type NoteProperty -name MinCPURes -value $DASMinMHz
		   $CPUObj | Add-Member -type NoteProperty -name MaxCPUNumVM -value $MaxCPUNumVM
			$CPUObj | Add-Member -type NoteProperty -name MaxCPURes -value $MaxCPURes
			$CPUObj | Add-Member -type NoteProperty -name MaxCPUResVM -value $MaxCPUResVM
			$CPUObj | Add-Member -type NoteProperty -name MaxCPUs -value $MaxNumCPU
			$CPUObj | Add-Member -type NoteProperty -name VMCapacityCPU -value $ClusterVMCapacityCPU
 
			$MemObj = New-Object System.Object
			$MemObj | Add-Member -type NoteProperty -name ClusterMemRes -value $viMemRes
			$MemObj | Add-Member -type NoteProperty -name DefaultMemRes -value $DASMemDefault
			$MemObj | Add-Member -type NoteProperty -name MinMemRes -value $DASMinMemory
			$MemObj | Add-Member -type NoteProperty -name MaxMemRes -value $MaxMemRes
			$MemObj | Add-Member -type NoteProperty -name MaxMemResVM -value $MaxMemResVM
			$MemObj | Add-Member -type NoteProperty -name VMCapacityMem -value $ClusterVMCapacityMEM
 
			$OutObj = New-Object System.Object
			$OutObj | Add-Member -type NoteProperty -name AdmissionControl -value $viClusterControl
			$OutObj | Add-Member -type NoteProperty -name CPU -value $CPUObj
			$OutObj | Add-Member -type NoteProperty -name FailoverHosts -value $viHostFailures
			$OutObj | Add-Member -type NoteProperty -name HostCount -value $viHostCount
			$OutObj | Add-Member -type NoteProperty -name Memory -value $MemObj
			$OutObj | Add-Member -type NoteProperty -name RunningVMs -value $VMCount
			$OutObj | Add-Member -type NoteProperty -name VIServer -value $viServerName
			$OutObj | Add-Member -type NoteProperty -name VICluster -value $viClusterName
			$OutObj | Add-Member -type NoteProperty -name VMCapacity -value $ClusterVMCapacity	
 
			return($outObj)
	}
	else
	{
		# Write usage info
		Write-Host ("")
		Write-Host ("-------------------------------------")
		Write-Host ("Get-HACapacity.ps1 Usage:")
		Write-Host( "You must specify the following parameters: ")
		Write-Host ("     '-ServerName '  where  is the name of the VirtualCenter Server")
		Write-Host("     '-ClusterName '  where  is the name of the cluster to query")
		Write-Host ("")
		}
}

Let me know if you have any problems with it or would like more info..

– Mark