Archive

Posts Tagged ‘Powershell’

Powershell Power! (Part Deux)

February 23rd, 2009 Mark A. Weaver No comments
Rating 3.50 out of 5

Okay, so this is the second installment of my little tutorial-thingy for Powershell.  After much thought on where I want this to go, I figured the next logical step would be to talk about setting up your Powershell (“PoSh”) environment.

So, let’s put together a little laundry-list of tools you may want to procure.  Just download the bits and save them for later.  We will go through some of these in more detail.

  1. Powershell installation bits (requires at least .NET 2.0 Framework)
  2. PowerTab from ThePowerShellGuy (Most EXCELLENT Site for all things PoSh)
  3. Quest PowerGUI (A powerful FREE GUI and IDE for PoSh) I won’t cover this installation here, but it is pretty straight forward.

That will probably be enough to get moving.

The Powershell install should be fairly straight forward.  Just take all the default options and let-her-role.

NOTE: If you want to install a newer version of Powershell, you will need to Uninstall the previous version.  This is kinda sucky, but not too bad.  To Uninstall it, you can go to Add/Remove Programs and look for it, but you may not see it if you have “Show Updates” option off.  It probably will show up as “Window Powershell”.

To install PowerTab, unzip the downloaded file to a folder you want it to live permanently.  I normally pick something like “C:\Program Files\PowerTab” so it is where all my other programs live.

Now open a command shell and start Powershell by typing in “powershell” and hitting Enter.

This may take a few seconds to launch, but if successful you should see your new and shiny Powershell prompt.   The first thing to do before anything else make it so we can actually run scripts.

Out-of-the-box, Powershell is delivered secure.  SO secure, in fact, that you can NOT run ANY scripts without making it a little less secure.  I will probably discuss this in more detail later or pressure my buddy Mike to write about it on his blog (this is more up his alley than mine).

Anyway…at your PoSh prompt type in the cmdlet:

Set-ExecutionPolicy RemoteSigned

If successful, you should be kicked back to your prompt.  Now we can move forward with the PowerTab install.

CD to the directory you install PowerTab to and run the “Setup.CMD” file to start the installer.  I normally just take all the defaults and let it go.  This will probably take a few minutes to finish up.

Now to show you a little about what PowerTab does for you….

If you type “Get-” and then hit the TAB key you should see a popup window with all sorts of fun things.  Basically PowerTab is like tab completion on STEROIDS.  It is very helpful for discovering what is available and such.  I hope you will take this opportunity to explore Powershell a bit.

You can get a list of all commands (called Commandlets) by typing in “Get-Command”.

I guess that is a fairly good place to break and talk about the “Cmdlets” (said CommandLets).

Cmdlets are the meat-and-potatoes of Powershell.  They are to Powershell what “cd” and “dir” are to the normal Windows command shell (cmd.exe).  Cmdlet names are constructed of 2 parts: a VERB and a NOUN.  If you look at the output of the “Get-Command” cmdlet, you will see lots of verbs on the left side of the “dash” in the cmdlet name: “Get”, “Out”, “Write”, etc.  The right side of the cmdlet name is the noun, or the thing that the verb acts on.

As you can see there are common Verbs and Nouns.  You can, in fact, do a “get-command -verb get” to list all commands that have the verb “Get”.  You can do the same for Nouns.  Go ahead and try that out on a few.

There are several cmdlets you should be using as you are learning the ins and outs of Powershell.  Probably the MOST helpful is, well “Get-Help”.

Get-Help is one I use on a VERY regular basis.  The general format for this one is:

  • “Get-Help <Cmdlet>”    : Gives basic info on the cmdlet
  • “Get-Help <Cmdlet> -Detailed”  : Gives  MUCH more info about the Cmdlet including some examples on using the cmdlet
  • “Get-Help <Cmdlet> -Full” : I think this gives ALL the info about the Cmdlet
  • “Get-Help <Cmdlet> -Examples” : Just gives you the usage examples.

Go ahead and try it now.  Do a “get-command”,  pick one that looks interesting to you and “get-help” on it.  This was crucial for me in learning the Powershell.

While I bring this part to a close I will challenge you to write something…well ANYTHING really.  The best way for me in learning was to pick a task and do it in Powershell.  The thought process for me was “Well, I could do this in vbScript in like 5 minutes, or I could take 30 minutes and do it in Powershell and learn a ton.”  If I have the time to do it in Powershell, I am doing it.

Some simple tasks would be to start using Powershell as your “normal” command shell.  This will get you used to using the cmdlets to navigate the environment and doing things.  Try NOT to use some of the default aliases that are “replacements” for the standard “cmd.exe” commands. These would include “type”, “dir”, etc.  I have been using the Powershell equivilant aliases…  “dir” becomes “Get-ChildItem” or simply “gci”.

The other thing I will challenge you to look at is the cmdlet “Get-Member”.  This will help you in this worthwhile venture into the wonderful world of Powershell.

I think the next session we will cover the notion that Powershell is “Object-Based”, which will be a good lead in from your “homework” on the “Get-Member” cmdlet.

Anyway, until next time…. happy Scripting!

– Mark

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