24
Jun/09
0

Create a vSwitch Port Overview with Powershell

WARNING: VMware vmotion does not check wether there are sufficient ports available on the virtual switch on the destination host. Migrating a vm to a host with insufficient ports will cause the vmotion to complete without warnings, yet the virtual NIC will be disconnected! This issue is descripbed in this KB article.
The solution to this problem is to create vSwitches with sufficient ports, obviously. Do you want to know how many ports are currently being used on every vSwitch in your environment? vSphere PowerCLI to the rescue! Try the following script:

$VC = Connect-VIServer "MyVCServer"
$myCol = @()
ForEach ($VMHost in (Get-VMHost | Sort Name))
	{
	ForEach ($VM in ($VMHost | Get-VM))
		{
		ForEach ($NIC in (Get-NetworkAdapter -VM $VM))
			{
			$myObj = "" | Select VMHost, VM, NIC, PortGroup, vSwitch
			$myObj.VMHost = $VMHost.Name
			$myObj.VM = $VM.Name
			$myObj.NIC = $NIC.Name
			$myObj.PortGroup = Get-VirtualPortGroup -VM $VM -Name $NIC.NetworkName
			$myObj.vSwitch = $myObj.PortGroup.VirtualSwitchName
			$myCol += $myObj
			}
		}
	}
$myCol | Group-Object VMHost, vSwitch -NoElement | Sort Name | Select Name, Count
Disconnect-VIServer -Confirm:$false
  • Share/Bookmark
12
Jun/09
1

Examine VMware CPU Ready Times with Powershell

When your (VMware) consolidation ratios are becoming high, it might be smart to keep an eye on your vm’s CPU Ready Times. Unfortunately, by default, the VI Client will only show realtime ready time statistics. Plus you’d have to look at each vm individually. Thank God VMware for the PowerCLI! Read this document for more information on how to interpret the results.

# Variables
$OutFile = "D:\Scripts\ReadyTimes.csv"
$VIServer = "MyVIServer.domain.local"
 
# Connect to Virtual Center
$VI = Connect-VIServer $VIServer
 
$myCol = @()
ForEach ($VMHost in (Get-VMHost | Sort Name))
	{
	ForEach ($VM in ($VMHost | Get-VM | Sort Name))
		{
		# Gather Stats
		$Ready = $VM | Get-Stat -Stat Cpu.Ready.Summation -RealTime
		$Used = $VM | Get-Stat -Stat Cpu.Used.Summation -RealTime
		$Wait = $VM | Get-Stat -Stat Cpu.Wait.Summation -RealTime
		For ($a = 0; $a -lt $VM.NumCpu; $a++)
			{
			$myObj = "" | Select VMHost, VM, Instance, %RDY, %USED, %WAIT
			$myObj.VMHost = $VMHost.Name
			$myObj.VM = $VM.Name
			$myObj.Instance = $a
			$myObj."%RDY" = [Math]::Round((($Ready | Where {$_.Instance -eq $a} | Measure-Object -Property Value -Average).Average)/200,1)
			$myObj."%USED" = [Math]::Round((($Used | Where {$_.Instance -eq $a} | Measure-Object -Property Value -Average).Average)/200,1)
			$myObj."%WAIT" = [Math]::Round((($Wait | Where {$_.Instance -eq $a} | Measure-Object -Property Value -Average).Average)/200,1)
			$myCol += $myObj
			}
		Clear-Variable Ready -ErrorAction SilentlyContinue 
		Clear-Variable Wait -ErrorAction SilentlyContinue 
		Clear-Variable Used -ErrorAction SilentlyContinue 
		Clear-Variable myObj -ErrorAction SilentlyContinue
		}
	}
 
Disconnect-VIServer -Confirm:$false
 
# Export and launch output
$myCol | Export-Csv $OutFile
Invoke-Item $OutFile
  • Share/Bookmark
4
Jun/09
3

Managing Scheduled Tasks Remotely Using Powershell

The following Powershell functions allow you to manage querying, creating and removing scheduled tasks on one or more computers remotely.
The functions use schtasks.exe, which is included in Windows. Unlike the Win32_ScheduledJob WMI class, the schtasks.exe commandline tool will show manually created tasks, as well as script-created ones. The examples show some, but not all parameters in action. I think the parameter names are descriptive enough to figure it out, really. If not, take a look at schtasks.exe /?. One tip: try piping a list of computer names to foreach-object and into this function.
Enjoy.
Hugo

Function Get-ScheduledTask
	{
	param([string]$ComputerName = "localhost")
	Write-Host "Computer: $ComputerName"
	$Command = "schtasks.exe /query /s $ComputerName"
	Invoke-Expression $Command
	Clear-Variable Command -ErrorAction SilentlyContinue
	Write-Host "`n"
	}
 
# EXAMPLE: Get-ScheduledTask -ComputerName Server01
 
Function Remove-ScheduledTask
	{
	param(
	[string]$ComputerName = "localhost",
	[string]$TaskName = "blank"
	)
	If ((Get-ScheduledTask -ComputerName $ComputerName) -match $TaskName)
		{
		If ((Read-Host "Are you sure you want to remove task $TaskName from $ComputerName(y/n)") -eq "y")
			{
			$Command = "schtasks.exe /delete /s $ComputerName /tn $TaskName /F"
			Invoke-Expression $Command
			Clear-Variable Command -ErrorAction SilentlyContinue
			}
		}
	Else
		{
		Write-Warning "Task $TaskName not found on $ComputerName"
		}
	}
 
# EXAMPLE: Remove-ScheduledTask -ComputerName Server01 -TaskName MyTask
 
Function Create-ScheduledTask
	{
	param(
	[string]$ComputerName = "localhost",
	[string]$RunAsUser = "System",
	[string]$TaskName = "MyTask",
	[string]$TaskRun = '"C:\Program Files\Scripts\Script.vbs"',
	[string]$Schedule = "Monthly",
	[string]$Modifier = "second",
	[string]$Days = "SUN",
	[string]$Months = '"MAR,JUN,SEP,DEC"',
	[string]$StartTime = "13:00",
	[string]$EndTime = "17:00",
	[string]$Interval = "60"	
	)
	Write-Host "Computer: $ComputerName"
	$Command = "schtasks.exe /create /s $ComputerName /ru $RunAsUser /tn $TaskName /tr $TaskRun /sc $Schedule /mo $Modifier /d $Days /m $Months /st $StartTime /et $EndTime /ri $Interval /F"
	Invoke-Expression $Command
	Clear-Variable Command -ErrorAction SilentlyContinue
	Write-Host "`n"
	}
 
# EXAMPLE: Create-ScheduledTask -ComputerName MyServer -TaskName MyTask02 -TaskRun "D:\scripts\script2.vbs"
  • Share/Bookmark
26
May/09
3

Get SQL database size using Windows Powershell

The following script examines servers from (part of) your Active Directory domain, identifies SQL servers and lists the instances with their total database sizes.

# Get-SQLSizes.ps1
# Created by Hugo Peeters
# http://www.peetersonline.nl
# Description: Finds SQL Servers in Active Directory and gets the total database size in GB.
 
#Region VARIABLES
	$SearchRoot = "OU=Servers,DC=domain,DC=local"
	$OutFile = 'D:\scripts\SQLSizes.csv'
	$Digits = 2
#EndRegion VARIABLES
 
#Region SCRIPT
	[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.Smo') | Out-Null
	$myCol = @()
	ForEach ($Server in (Get-QADComputer -SearchRoot $SearchRoot -SizeLimit 0 | Sort Name))
		{
		ForEach ($Instance in (Get-WmiObject -Class Win32_Service -ComputerName $Server.Name | Where {$_.Name -like 'MSSQL$*'}))
			{
			If ($Instance -eq $null){break}
			# Connect to SQL
			$InstanceString = "{0}\{1}" -f $Server.Name, $Instance.Name.Split('$')[1]
			$Sql = New-Object ('Microsoft.SqlServer.Management.Smo.Server') $InstanceString
			# Gather information
			$myObj = "" | Select Instance, TotalDBSizeGB
			$myObj.Instance = $InstanceString
			$myObj.TotalDBSizeGB = [Math]::Round((($Sql.Databases | ForEach {$_.Size} | Measure-Object -Sum).Sum * 1MB / 1GB),$Digits)
			$myCol += $myObj
			# Cleanup
			Clear-Variable Sql -ErrorAction SilentlyContinue
			Clear-Variable InstanceString -ErrorAction SilentlyContinue
			}
		}	
#EndRegion SCRIPT
 
#Region OUTPUT
	$myCol | Export-Csv $OutFile -NoTypeInformation
	Invoke-Item $OutFile
#EndRegion OUTPUT
  • Share/Bookmark
4
Apr/09
2

Synchronize WSUS with Powershell

Yesterday, I showed you how to script the WSUS Cleanup Wizard with Powershell. Today, the WSUS fun continues! Here’s how to use powershell to “manually” synchronize your WSUS server, i.e. download the latest updates.

#Region VARIABLES
 
# WSUS Connection Parameters:
[String]$updateServer = "myWSUSServer.domain.local"
[Boolean]$useSecureConnection = $False
[Int32]$portNumber = 80
 
#EndRegion VARIABLES
 
#Region SCRIPT
 
# Load .NET assembly
[void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
 
# Connect to WSUS Server
$Wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($updateServer,$useSecureConnection,$portNumber)
 
# Perform Synchronization
$Subscription = $Wsus.GetSubscription()
$Subscription.StartSynchronization()
 
#EndRegion SCRIPT

Download the script here: Synchronize-Wsus (rename to .ps1)

Enjoy!
Hugo

  • Share/Bookmark
3
Apr/09
12

WSUS Cleanup with Powershell

If you manage a Windows Server Update Services (WSUS) server, you probably run the Server Cleanup Wizard every once and a while. It removes old and superseded updates and computers that haven’t reported their status for more than 30 days. Wouldn’t it be nice to schedule such a cleanup to run every month? Too bad there’s no command line tool I know of that can help you out with this. Powershell to the rescue!
Powershell can not only run the built-in commandlets or even those added by snapins. It can leverage the full power of the .NET Framework. Browse the MSDN Library if you want to find more cool things you can do with it. Here’s a script that uses this information to run the cleanup wizard:

#Region VARIABLES
 
# WSUS Connection Parameters:
[String]$updateServer = "myWSUSServer.domain.local"
[Boolean]$useSecureConnection = $False
[Int32]$portNumber = 80
 
# Cleanup Parameters:
# Decline updates that have not been approved for 30 days or more, are not currently needed by any clients, and are superseded by an aproved update.
[Boolean]$supersededUpdates = $True
# Decline updates that aren't approved and have been expired my Microsoft.
[Boolean]$expiredUpdates = $True
# Delete updates that are expired and have not been approved for 30 days or more.
[Boolean]$obsoleteUpdates = $True
# Delete older update revisions that have not been approved for 30 days or more.
[Boolean]$compressUpdates = $True
# Delete computers that have not contacted the server in 30 days or more.
[Boolean]$obsoleteComputers = $True
# Delete update files that aren't needed by updates or downstream servers.
[Boolean]$unneededContentFiles = $True
 
#EndRegion VARIABLES
 
#Region SCRIPT
 
# Load .NET assembly
[void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
 
# Connect to WSUS Server
$Wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($updateServer,$useSecureConnection,$portNumber)
 
# Perform Cleanup
$CleanupManager = $Wsus.GetCleanupManager()
$CleanupScope = New-Object Microsoft.UpdateServices.Administration.CleanupScope($supersededUpdates,$expiredUpdates,$obsoleteUpdates,$compressUpdates,$obsoleteComputers,$unneededContentFiles)
$CleanupManager.PerformCleanup($CleanupScope)
 
#EndRegion SCRIPT

Download it here: Cleanup-Wsus (rename to .ps1)

Happy scheduling!

Hugo

  • Share/Bookmark
21
Jan/09
0

Puzzle

Just having a bit of fun with Powershell:

48 6F 6C 64 20 66 61 73 74 20 74 6F 20 64 72 65 61 6D 73 A 46 6F 72 20 69 66 20 64 72 65 61 6D 73 20 64 69 65 A 4C 69 66 65 20 69 73 20 61 20 62 72 6F 6B 65 6E 2D 77 69 6E 67 65 64 20 62 69 72 64 A54 68 61 74 20 63 61 6E 6E 6F 74 20 66 6C 79 2E A 48 6F 6C 64 20 66 61 73 74 20 74 6F 20 64 72 65 61 6D 73 A 46 6F 72 20 77 68 65 6E 20 64 72 65 61 6D 73 20 67 6F A 4C 69 66 65 20 69 73 20 61 20 62 61 72 72 65 6E 20 66 69 65 6C 64 A 46 72 6F 7A 65 6E 20 77 69 74 68 20 73 6E 6F 77 2E 20 A A 2D 2D 4C 61 6E 67 73 74 6F 6E 20 48 75 67 68 65 73

Solution:
convert-texttohexandback

  • Share/Bookmark
19
Jan/09
16

Check VMware Configuration with Powershell

I have promised you I would post this script, so here it is!

This Powershell script generates an overview of any items that are not available to every ESX server in a VMware cluster. These items might prevent your vm’s being vmotioned by DRS or restarted by HA. Pretty serious business, I’d say!

The items involved are:
1. datastores
2. LUNs (important when using Raw Device Mappings)
3. port groups

The output is a nicely formatted HTML page showing not only which items are misconfigured, but also where the are available and where they are absent.

Here’s an example:
Compare Screenshot

And here’s the script:
Compare-Clusters (Rename to .ps1)

Enjoy!
Hugo

  • Share/Bookmark
16
Jan/09
0

Compare Cluster Datastores with Powershell

I showed you before how to compare the datastores for two ESX Servers using the VI Toolkit. But ideally, one would like to compare all ESX servers in a cluster to ensure VMotion and HA compatibility.
So I started scripting and it turns out to be pretty simple: only 4 lines of code in Powershell! It does the comparison for all your clusters and returns clean little tables with datastores you should investigate.

SCRIPT CODE:

ForEach ($Cluster in (Get-Cluster | Sort Name))
{
$VMHosts = Get-Cluster $Cluster.Name | Get-VMHost
$Datastores = $VMHosts | Get-Datastore
$VMHosts | ForEach {Compare-Object $Datastores ($_ | Get-Datastore)} | ForEach {$_.InputObject} | Sort Name | Select @{N=$Cluster.Name;E={$_.Name}} -Unique | Format-Table
}

SAMPLE OUTPUT:

TEST CLUSTER 1
——————
DATASTORE1
LOCAL01
LOCAL02
LOCAL03

TEST CLUSTER 2
——————
DATASTORE2
DATASTORE3
LOCAL06
LOCAL07
LOCAL08
LOCAL09

Coming very soon: a full-blown script that compares datastores, LUNs and portgroups across your clusters ánd identifies exactly where the differences are! Stay tuned…

  • Share/Bookmark
8
Jan/09
22

Another way to gather VMware disk info with Powershell

I’ve created another way to gather and display VMware Virtual Disk information with the Powershell VI Toolkit.

The attached script generates a csv-file with all Virtual Machines’ Disks, in which Datastore they are stored, the LUN IDs of the extents that make up this Datastore (in HEX) and the Vendor of the SAN those LUNs are on (just in case you have multiple). Simpy a great way to determine which LUNs are used by which virtual server(s) in a complex environment.

diskinfo

By the way: the script is filled with comments to allow you to learn how it works.

create-vmdiskoverview (Rename to .ps1)

Enjoy!

Hugo

  • Share/Bookmark