-
Basic VMware Cluster Capacity Check with PowerCLI
Posted on January 18th, 2012 7 commentsI recently needed to provide a high level capacity overview per VMware cluster looking at some metrics of interest that were being used as a guide to the capacity state of a cluster. Note: these are by no means definitive or the ones you should be using in your environment, but for these purposes they met the requirements. The metrics I looked at per cluster were the ratio of vCPUs to pCPUs, the amount of Effective, Allocated and average Active Memory and the amount of Free Diskspace.
A couple of things to note:
1.The section below on datastore freespace filters out the local datastore which contains the name of the host.
$VMHost = $Cluster | Get-VMHost | Select-Object -Last 1 $HostName = ($VMHost.name -split ".", 0, "simplematch")[0] $ClusterFreeDiskspaceGB = ($VMHost | Get-Datastore | Where-Object {$_.Name -notmatch $HostName} | Measure-Object -Property FreeSpaceGB -Sum).Sum2. I’ve recently changed the way I create custom objects to output reports with. For a long time I have used the cheat way of Select-Object , partly because of performance and partly because you can’t control the order of properties in New-Object. These are being addressed in PowerShell v3 (see here and here) so I thought it was about time to make the switch. This means for the time being that when working with the output you need to pipe it to Select-Object to control the order of the output, e.g.
Get-Cluster | Get-ClusterCapacityCheck | Select-Object Cluster,ClusterCPUCores,ClusterAllocatedvCPUs,ClustervCPUpCPURatio,ClusterEffectiveMemoryGB,
ClusterAllocatedMemoryGB,ClusterActiveMemoryPercentage,ClusterFreeDiskspaceGB
function Get-ClusterCapacityCheck { <# .SYNOPSIS Retrieves basic capacity info for VMware clusters .DESCRIPTION Retrieves basic capacity info for VMware clusters .PARAMETER ClusterName Name of the computer to test the services for .EXAMPLE PS C:\> Get-ClusterCapacityCheck -ClusterName Cluster01 .EXAMPLE PS C:\> Get-Cluster | Get-ClusterCapacityCheck .NOTES Author: Jonathan Medd Date: 18/01/2012 #> [CmdletBinding()] param( [Parameter(Position=0,Mandatory=$true,HelpMessage="Name of the cluster to test", ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$true)] [System.String] $ClusterName ) begin { $Finish = (Get-Date -Hour 0 -Minute 0 -Second 0) $Start = $Finish.AddDays(-1).AddSeconds(1) New-VIProperty -Name FreeSpaceGB -ObjectType Datastore -Value { param($ds) [Math]::Round($ds.FreeSpaceMb/1KB,0) } -Force } process { $Cluster = Get-Cluster $ClusterName $ClusterCPUCores = $Cluster.ExtensionData.Summary.NumCpuCores $ClusterEffectiveMemoryGB = [math]::round(($Cluster.ExtensionData.Summary.EffectiveMemory / 1KB),0) $ClusterVMs = $Cluster | Get-VM $ClusterAllocatedvCPUs = ($ClusterVMs | Measure-Object -Property NumCPu -Sum).Sum $ClusterAllocatedMemoryGB = [math]::round(($ClusterVMs | Measure-Object -Property MemoryMB -Sum).Sum / 1KB) $ClustervCPUpCPURatio = [math]::round($ClusterAllocatedvCPUs / $ClusterCPUCores,2) $ClusterActiveMemoryPercentage = [math]::round(($Cluster | Get-Stat -Stat mem.usage.average -Start $Start -Finish $Finish | Measure-Object -Property Value -Average).Average,0) $VMHost = $Cluster | Get-VMHost | Select-Object -Last 1 $ClusterFreeDiskspaceGB = ($VMHost | Get-Datastore | Where-Object {$_.Extensiondata.Summary.MultipleHostAccess -eq $True} | Measure-Object -Property FreeSpaceGB -Sum).Sum New-Object -TypeName PSObject -Property @{ Cluster = $Cluster.Name ClusterCPUCores = $ClusterCPUCores ClusterAllocatedvCPUs = $ClusterAllocatedvCPUs ClustervCPUpCPURatio = $ClustervCPUpCPURatio ClusterEffectiveMemoryGB = $ClusterEffectiveMemoryGB ClusterAllocatedMemoryGB = $ClusterAllocatedMemoryGB ClusterActiveMemoryPercentage = $ClusterActiveMemoryPercentage ClusterFreeDiskspaceGB = $ClusterFreeDiskspaceGB } } } -
Using PowerShell To Check That Windows Server Services Set To Automatic Have Started
Posted on January 11th, 2012 2 commentsFollowing on from the blog post Testing TCP Port Response from PowerShell which provided a means to check that servers had fully rebooted after a patching and reboot cycle, I needed to take this one step further and check that all of the Windows Services set to Automatic successfully started after the reboot.
This should be pretty straightforward since we have a Get-Service cmdlet. Unfortunately however, this cmdlet does not return a StartMode parameter, i.e. it’s not possible to tell whether the Startup Type has been set to Automatic, Manual or Disabled. This is quite a large gap in my opinon – if you agree with me you can vote to get it included in a future release here. Of course with PowerShell there’s usually another way to achieve the same objective and using Get-WMIObject it is possible to find out the Startup Type of the service.
Get-WmiObject Win32_Service -ComputerName $ComputerName -Filter "StartMode='Auto' AND State='Stopped' AND Name!='SysmonLog'"
Notice that we filter out the Perfmon service (SysmonLog) since it is rarely in a started state.
One other thing to watch out for in this script is that the section
catch [System.Exception]
which is there to catch any WMI queries that fail, e.g. the server hasn’t rebooted properly or the correct permissions do not exist to make the WMI query, will not pick up any of these failures. This is because try / catch will only catch terminating errors and the WMI failures are non terminating. We can work around this by setting:
$ErrorActionPreference = "Stop"
and then back to normal afterwards:
$ErrorActionPreference = "Continue"
The script accepts pipeline input, so for example you could run it like:
Get-Content servers.txt | ./Get-AutomaticServiceState.ps1
Here it is:
<# .SYNOPSIS Retrieves any Windows services set to Automatic and are not running .DESCRIPTION Retrieves any Windows services set to Automatic and are not running .PARAMETER ComputerName Name of the computer to test the services for .EXAMPLE PS C:\> Get-AutomaticServiceState -ComputerName Server01 .EXAMPLE PS C:\> Get-Content servers.txt | Get-AutomaticServiceState .NOTES Author: Jonathan Medd Date: 11/01/2012 #> [CmdletBinding()] param( [Parameter(Position=0,Mandatory=$true,HelpMessage="Name of the computer to test", ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$true)] [Alias('CN','__SERVER','IPAddress','Server')] [System.String] $ComputerName ) process { try { # Set ErrorActionPreference to Stop in order to catch non-terminating WMI errors $ErrorActionPreference = "Stop" # Query the server via WMI and exclude the Performance Logs and Alerts Service $WMI = Get-WmiObject Win32_Service -ComputerName $ComputerName -Filter "StartMode='Auto' AND State='Stopped' AND Name!='SysmonLog'" } catch [System.Exception] { $WMI = “” | Select-Object SystemName,Displayname,StartMode,State $WMI.SystemName = $ComputerName $WMI.Displayname = "Unable to connect to server" $WMI.StartMode = "" $WMI.State = "" } finally { $ErrorActionPreference = "Continue" } if ($WMI){ foreach ($WMIResult in $WMI){ $MYObject = “” | Select-Object ComputerName,ServiceName,StartupMode,State $MYObject.ComputerName = $WMIResult.SystemName $MYObject.ServiceName = $WMIResult.Displayname $MYObject.StartupMode = $WMIResult.StartMode $MYObject.State = $WMIResult.State $MYObject } } } -
Obtaining Symantec Endpoint Protection Version Info with PowerShell
Posted on December 23rd, 2011 No commentsRight, let’s set this one out. I do not, have not ever, nor probably will ever will like any AV Enterprise Management Products. However, sometimes you have to work with them and frequently the data in the Management Product does not actually reflect the end user / server estate. The below function will query the registry of a remote machine(s) and report back the state of the installed Symantec SEP client to help perform a true up.
The PatternFileDate value stored in HKEY_LOCAL_MACHINE\SOFTWARE\Symantec\Symantec Endpoint Protection\AV needs a little figuring out, this posting helps figure it out.
You can get the Info from this Registry Location
HKEY_LOCAL_MACHINE\SOFTWARE\Symantec\Symantec Endpoint Protection\AV
On this Key you can find two Values
PatternFileDate : Current Definition date
PatternFileRevision : RevisionThese are Hexadecimal values
Example:
PatternFileDate : 27090e – 2009 Oct 14
27090e – YYMMDD Format
27 – 2009
27 Hex is 39 Decimal, this value is since 1970. So 1970+39 = 200909 is October (00- Jan, 0B – Dec)
0e Hex - 14 in decimalPatternFileRevision : 16Hex – 22
16 HEX is 22 in Decimal
function Get-SEPVersion { <# .SYNOPSIS Retrieve Symantec Endpoint Version, Definition Date and Sylink Group .DESCRIPTION Retrieve Symantec Endpoint Version, Definition Date and Sylink Group .PARAMETER ComputerName Name of the computer to query SEP info for .EXAMPLE PS C:\> Get-SEPVersion -ComputerName Server01 .EXAMPLE PS C:\> $servers | Get-SEPVersion .NOTES Author: Jonathan Medd Date: 23/12/2011 #> [CmdletBinding()] param( [Parameter(Position=0,Mandatory=$true,HelpMessage="Name of the computer to query SEP for", ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)] [Alias('CN','__SERVER','IPAddress','Server')] [System.String] $ComputerName ) begin { # Create object to enable access to the months of the year $DateTimeFormat = New-Object System.Globalization.DateTimeFormatInfo # Set Registry keys to query $SMCKey = "SOFTWARE\\Symantec\\Symantec Endpoint Protection\\SMC" $AVKey = "SOFTWARE\\Symantec\\Symantec Endpoint Protection\\AV" $SylinkKey = "SOFTWARE\\Symantec\\Symantec Endpoint Protection\\SMC\\SYLINK\\SyLink" } process { try { # Connect to Registry $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine",$ComputerName) # Obtain Product Version value $SMCRegKey = $reg.opensubkey($SMCKey) $SEPVersion = $SMCRegKey.GetValue('ProductVersion') # Obtain Pattern File Date Value $AVRegKey = $reg.opensubkey($AVKey) $AVPatternFileDate = $AVRegKey.GetValue('PatternFileDate') # Convert PatternFileDate to readable date $AVYearFileDate = [string]($AVPatternFileDate[0] + 1970) $AVMonthFileDate = $DateTimeFormat.MonthNames[$AVPatternFileDate[1]] $AVDayFileDate = [string]$AVPatternFileDate[2] $AVFileVersionDate = $AVDayFileDate + " " + $AVMonthFileDate + " " + $AVYearFileDate # Obtain Sylink Group value $SylinkRegKey = $reg.opensubkey($SylinkKey) $SylinkGroup = $SylinkRegKey.GetValue('CurrentGroup') } catch [System.Management.Automation.MethodInvocationException] { $SEPVersion = "Unable to connect to computer" $AVFileVersionDate = "" $SylinkGroup = "" } $MYObject = “” | Select-Object ComputerName,SEPProductVersion,SEPDefinitionDate,SylinkGroup $MYObject.ComputerName = $ComputerName $MYObject.SEPProductVersion = $SEPVersion $MYObject.SEPDefinitionDate = $AVFileVersionDate $MYObject.SylinkGroup = $SylinkGroup $MYObject } } -
Configuring HP EVA Recommended Settings for ESXi via PowerCLI
Posted on December 21st, 2011 2 commentsThe HP Enterprise Virtual Array Family with VMware vSphere 4.0 , 4.1 AND 5.0 Configuration Best Practises Guide, available here, contains many recommendations for ESXi configuration. There are a number of recommended settings in this document to enhance the storage performance, a subset of which I have picked as appropriate for the environment and then needed to configure them on all ESXi hosts.
They can be implemented via PowerCLI and the below script demonstrates how these different types of settings can be configured. The most interesting one for me was setting the default Path Selection Policy to VMW_PSP_RR. The guide recommends you use the following command from the ESXi console:
esxcli nmp satp setdefaultpsp -satp VMW_SATP_ALUA -psp VMW_PSP_RR
With the introduction of the Get-ESXCLI cmdlet we can now carry out the equivalent from PowerCLI. Get-EsxCLI requires a direct connection to the ESXi host rather than from vCenter, so all the settings in this script are configured via a direct connection to the ESXi host
Warning: Before carrying out any of these types of changes make sure you talk to your Storage Adminstrator to confirm what is appropriate for your own environment. Other array vendors offer different recommendations so be sure to check their documentation for similar settings.
<# .SYNOPSIS Implement HP Recommended Settings for EVA SAN .DESCRIPTION Implement HP Recommended Settings for EVA SAN .PARAMETER HostName Name of the ESXi host to configure the settings on .EXAMPLE PS C:\> ./Set-HPEVAESXiConfig.ps1 -Hostname ESX01 .EXAMPLE PS C:\> Get-Content ESXServers.txt | ./Set-HPEVAESXiConfig.ps1 .NOTES Author: Jonathan Medd Date: 21/12/2011 #> [CmdletBinding()] param( [Parameter(Position=0,Mandatory=$true,HelpMessage="Name of the ESXi host to configure the settings on", ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)] [Alias('IPAddress','Server','ComputerName')] [System.String] $HostName ) begin { Write-Host "Please enter credentials to connect to the ESXi hosts" -ForegroundColor:Yellow $Credential = Get-Credential $UserName = $Credential.GetNetworkCredential().UserName $Password = $Credential.GetNetworkCredential().Password } process { Connect-VIServer $Hostname -User $Username -Password $Password | Out-Null Write-Host "Setting Disk.DiskMaxIOSize Advanced Option" Set-VMHostAdvancedConfiguration -VMHost $Hostname -Name Disk.DiskMaxIOSize -Value 128 | Out-Null Write-Host "Changing any LUNs with MultipathPolicy set to MostRecentlyUsed to be RoundRobin instead" Get-ScsiLun -VmHost $Hostname -LunType "disk" | Where-Object {$_.MultipathPolicy –eq "MostRecentlyUsed"} | Set-ScsiLun -MultipathPolicy "RoundRobin" | Out-Null Write-Host "Setting the default PSP to be VMW_PSP_RR" $esxCli = Get-EsxCli –Server $Hostname $esxCli.nmp.satp.setdefaultpsp("VMW_PSP_RR", "VMW_SATP_ALUA") Write-Host "Disconnecting from Host" $DefaultVIServer | Disconnect-VIServer -Confirm:$false }esxi, HP, powercli, powershell, vmware esxi, HP, powercli, powershell, vmware -
Testing TCP Port Response from PowerShell
Posted on December 20th, 2011 9 commentsRecently I was listening to the PowerScripting Podcast and Hal mentioned a Test-TCPPort function he had put together a while back. I had a similar need to be able to test a bunch of machines post reboot, that they had come back successfully and a Ping test wouldn’t do since that didn’t necessarily mean that Windows has successfully booted
So taking inspiration from that post I put together the following script (I convert it to a function for my own use, but it’s easier for my colleagues to use as a script) which will test by default RDP response from servers and report the results. A few examples of how to use it:
Test a single server
.\Test-PortResponse.ps1 -ComputerName Server01 | Format-Table -AutoSize
Testing multiple servers
Get-Content servers.txt | .\Test-PortResponse.ps1 | Format-Table -AutoSize
Testing multiple servers on port 22 and exporting the results to csv
Get-Content servers.txt | .\Test-PortResponse.ps1 -Port 22 | Export-Csv Ports.csv -NoTypeInformation
Here’s the code you can use.
<# .SYNOPSIS Test the response of a computer to a specific TCP port .DESCRIPTION Test the response of a computer to a specific TCP port .PARAMETER ComputerName Name of the computer to test the response for .PARAMETER Port TCP Port number to test .EXAMPLE PS C:\> ./Test-PortResponse.ps1 -ComputerName Server01 .EXAMPLE PS C:\> Get-Content Servers.txt | ./Test-PortResponse.ps1 -Port 22 .NOTES Author: Jonathan Medd Date: 20/12/2011 #> [CmdletBinding()] param( [Parameter(Position=0,Mandatory=$true,HelpMessage="Name of the computer to test", ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$true)] [Alias('CN','__SERVER','IPAddress','Server')] [System.String] $ComputerName, [Parameter(Position=1)] [ValidateRange(1,65535)] [Int] $Port = 3389 ) process { $Connection = New-Object Net.Sockets.TcpClient try { $Connection.Connect($ComputerName,$Port) if ($Connection.Connected) { $Response = “Open” $Connection.Close() } } catch [System.Management.Automation.MethodInvocationException] { $Response = “Closed / Filtered” } $Connection = $null $MYObject = “” | Select-Object ComputerName,Port,Response $MYObject.ComputerName = $ComputerName $MYObject.Port = $Port $MYObject.Response = $Response $MYObject } -
UK PowerShell User Group December 2011 – Use the WSMAN cmdlets to retreive WMI information
Posted on December 14th, 2011 No commentsThe UK PowerShell User Group for December 2011 will take place at 19.30 GMT on Thursday December 15t. The topic is ‘Use the WSMAN cmdlets to retreive WMI information and see a demo of the new WMI API’s CIM cmdlets in PowerShell v3 CTP 2′. I’m looking forward to seeing the new CIM cmdlets from V3 CTP2 since I haven’t had chance to play with those yet. Details from Richard Siddaway’s blog are below:
When: Thursday, Dec 15, 2011 7:30 PM (GMT) Where: Virtual *~*~*~*~*~*~*~*~*~*
Discover how to use the WSMAN cmdlets to retreive WMI information and see a demo of the new WMI API’s CIM cmdlets in PowerShell v3 CTP 2
Notes
Richard Siddaway has invited you to attend an online meeting using Live Meeting.
Join the meeting.
Audio Information
Computer Audio
To use computer audio, you need speakers and microphone, or a headset.
First Time Users:
To save time before the meeting, check your system to make sure it is ready to use Microsoft Office Live Meeting.
Troubleshooting
Unable to join the meeting? Follow these steps:- Copy this address and paste it into your web browser:
https://www.livemeeting.com/cc/usergroups/join
- Copy and paste the required information:
Meeting ID: PJSH3M
Entry Code: gG/C-75(m
Location: https://www.livemeeting.com/cc/usergroups
If you still cannot enter the meeting, contact support
Notice
Microsoft Office Live Meeting can be used to record meetings. By participating in this meeting, you agree that your communications may be monitored or recorded at any time during the meeting. - Copy this address and paste it into your web browser:
-
Reporting on Windows File Server Shares and NTFS Permissions with PowerShell
Posted on December 8th, 2011 No commentsI recently had a requirement to audit the Share and NTFS permissions of a Windows File Server. PowerShell contains the Get-ACL cmdlet which makes retreving the NTFS permissions fairly straightforward, but for the Share permissions it is not so easy, but we can make use of WMI and the Win32_LogicalShareSecuritySetting class.
The below forum post details some discussion around using this class to find the Share permissions and unsurprisingly the legendary Shay Levy provides the solution.
http://groups.google.com/group/powershell-users/browse_thread/thread/43f06ce172e68c38?pli=1
The following script makes use of this code and adds some parameters depending on your requirements.
<# .SYNOPSIS Retrieve report of share permissions .DESCRIPTION Retrieve report of share permissions .PARAMETER ComputerName Computer name to retrieve share permissions from .PARAMETER Share Name of the share to retrieve permissions from (optional) .PARAMETER OutputFile Name of the file to output the report to (optional) .EXAMPLE PS C:\> Get-SharePermissions.ps1 -ComputerName Server01 -Share Share01 -OutputFile C:\Scripts\SharePermissions.csv .EXAMPLE PS C:\> Get-SharePermissions.ps1 -ComputerName Server01 .NOTES Author: Jonathan Medd Date: 06/12/2011 Version: 0.1 #> [CmdletBinding()] param( [Parameter(Position=0)] [System.String] $ComputerName = '.', [Parameter(Position=1)] [System.String] $Share, [Parameter(Position=2)] [System.String] $OutputFile ) function Translate-AccessMask($val){ Switch ($val) { 2032127 {"FullControl"; break} 1179785 {"Read"; break} 1180063 {"Read, Write"; break} 1179817 {"ReadAndExecute"; break} -1610612736 {"ReadAndExecuteExtended"; break} 1245631 {"ReadAndExecute, Modify, Write"; break} 1180095 {"ReadAndExecute, Write"; break} 268435456 {"FullControl (Sub Only)"; break} default {$AccessMask = $val; break} } } function Translate-AceType($val){ Switch ($val) { 0 {"Allow"; break} 1 {"Deny"; break} 2 {"Audit"; break} } } # Create calculated properties $ShareProperty = @{n="Share";e={$ShareName}} $AccessMask = @{n="AccessMask";e={Translate-AccessMask $_.AccessMask}} $AceType = @{n="AceType";e={Translate-AceType $_.AceType}} $Trustee = @{n="Trustee";e={$_.Trustee.Name}} if ($Share){ $filter="name='$Share'" $WMIQuery = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -ComputerName $ComputerName -filter $filter | ForEach-Object { $ShareName = $_.name $_.GetSecurityDescriptor().Descriptor.DACL | Select-Object $Shareproperty,$AccessMask,$AceType,$Trustee} } else { $WMIQuery = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -ComputerName $ComputerName | ForEach-Object { $ShareName = $_.name $_.GetSecurityDescriptor().Descriptor.DACL | Select-Object $Share,$AccessMask,$AceType,$Trustee } } if ($OutputFile){ $WMIQuery | Export-Csv $OutputFile -NoTypeInformation } else { $WMIQuery | Format-Table -AutoSize }For NTFS permissions Jeff Hicks has a very useful post for creating NTFS ACL reports.
http://jdhitsolutions.com/blog/2011/06/creating-acl-reports/
The following is a script based off some of the ideas in that post which you can use for generating a report depending on your requirements.
<# .SYNOPSIS Retrieve report of NTFS permissions .DESCRIPTION Retrieve report of NTFS permissions .PARAMETER ComputerName Computer name to retrieve NTFS permissions from .PARAMETER Folder Name of the NTFS path to retrieve permissions from .PARAMETER Recurse Retrieve permissions from subfolders and files .PARAMETER OutputFile Name of the file to output the report to (optional) .EXAMPLE PS C:\> Get-NTFSPermissions.ps1 -ComputerName Server01 -Folder D$\Home -OutputFile C:\Scripts\NTFSPermissions.csv .EXAMPLE PS C:\> Get-NTFSPermissions.ps1 -Folder D:\Home -Recurse .NOTES Author: Jonathan Medd Date: 07/12/2011 Version: 0.1 #> [CmdletBinding()] param( [Parameter(Position=0)] [System.String] $ComputerName = '.', [Parameter(Position=1,Mandatory=$true,HelpMessage="Name of the NTFS path to retrieve permissions from")] [System.String] $Folder, [Parameter(Position=2)] [Switch] $Recurse, [Parameter(Position=3)] [System.String] $OutputFile ) # Set the Path variable dependent on whether its for a remote machine if ($ComputerName -eq '.'){ $Path = $Folder } else { $Path = "\\$ComputerName\$Folder" } if ($OutputFile){ Get-Childitem $Path -Recurse:$Recurse | ForEach-Object {Get-Acl $_.FullName} | Select-Object @{Name="Path";Expression={$_.PSPath.Substring($_.PSPath.IndexOf(":")+2) }},@{Name="Type";Expression={$_.GetType()}},Owner -ExpandProperty Access | Export-CSV $OutputFile -NoTypeInformation } else { Get-Childitem $Path -Recurse:$Recurse | ForEach-Object {Get-Acl $_.FullName} | Select-Object @{Name="Path";Expression={$_.PSPath.Substring($_.PSPath.IndexOf(":")+2) }},@{Name="Type";Expression={$_.GetType()}},Owner -ExpandProperty Access | Format-Table -AutoSize } -
PowerShell V3 CTP2 – Now Available
Posted on December 6th, 2011 1 commentThe second Community Technology Preview of PowerShell V3 is now available. This pre-beta release gives of a flavour of areas of change which may appear in the final release. A CTP has an emphasis on Community , i.e. the PowerShell team is looking for plenty of feedback for this release while they still have time to change things. Below are items logged on Connect by the community which have been fixed since the release of CTP1 – so if you find an issue in your testing, please log it on Connect so it can be reviewed and potentially resolved.
689302 Unable to catch PSRemotingTransportException 690139 Get-Command gets duplicated result if a requested script path contains “..”. 676882 Out-GridView and properties with dots 687776 ISE Editor Enhancements 687886 2-pane “more console-like” mode for ISE 688630 PowerShell ISE v3 – UserEnterToSelectInCommandPaneIntellisense should be on by default 690164 V3 – out-gridview – remove a criteria close the grid window 690556 Tab Complete in Remote Session 690784 PS3CTP1 – Object casting regression 690864 Import-Module should check the required PowerShell version before anything else 690895 PS3CTP1: PowerShell.exe shows THROWN error Message in normal output color 691206 PoshV3CTP1: PowerShell Events do not trigger when used with UI (WPF & Windows Forms) 691439 Having an append ability in Export-CSV. 692617 StopProcessing doesn’t work in v3 692776 PS3CTP1: Variables as property names BROKEN with Assignment Operators 693754 Powershell 3.0 ISE editor corrupts text 694600 Run with Powershell not executing scripts 694940 NestedModules are unloaded from GLOBAL scope with the parent module. 694942 NestedModules doesn’t support specifying the version 695755 v3 CTP1: Breaking change – DayOfWeek and left-hand rule 695978 PS3CTP1: REGRESSION: Get-Member -Static Error 697131 v3 CTP1: Char[] not reversed by Array.Reverse static method 704136 Divide by Zero $? Test Returns True PowerShell V3 CTP2 is part of the Windows Management Framework (WMF) 3.0 CTP2 and can be installed on the following Windows configurations.
Operating System SP Level SKUs Languages Windows 7 SP1 All English Windows Server 2008 R2 SP1 and greater All but IA64 English Full details on other changes in CTP2 are detailed on the PowerShell Team Blog:
—————————————————————————————————————————————————————————————————————————————————-
I’m pleased to announce that the Community Technology Preview #2 (CTP2) is available for download.
Windows Management Framework 3.0 CTP2 makes some updated management functionality available to be installed on Windows 7 SP1 & Windows Server 2008 R2 SP1. Windows Management Framework 3.0 contains Windows PowerShell 3.0, WMI & WinRM.
IMPORTANT: If you have WMF3.0 CTP1 installed, you must uninstall it before installing CTP2.
Overview of changes since WMF 3.0 CTP1
1. Customer Reported Bug Fixes
Many customer reported bugs have been fixed since the WMF 3.0 CTP1. The release notes contains a list of bug titles, but please check Connect for full details.2. Single Command Pane in Windows PowerShell ISE
The Command and Output panes in Windows PowerShell ISE have been combined into a single Command pane that looks and behaves like the Windows PowerShell console.3. Updatable Help
The WMF 3.0 CTP1 release notes described a new Updatable Help system in Windows PowerShell 3.0 and included a copy of the help content. The Updatable Help system is now active on the Internet. To download and update help files, type: Update-Help.4. Windows PowerShell Workflows
A number of enhancements have been made in the scripting experience for Windows PowerShell Workflows, including new keywords: Parallel, Sequence & Inlinescript. A document describing these changes will be published to the download page shortly.5. Remote Get-Module
The Get-Module cmdlet now supports implicit remoting. You can now use the new PSSession and CIMSession parameters of the Get-Module cmdlet to get the modules in any remote session or CIM session. A number of other module enhancements are listed in the release notes.Feedback & Bugs
We welcome any feedback or bug submissions to the Windows PowerShell Connect site: http://connect.microsoft.com/PowerShellAdditional Information:
This software is a pre-release version. Features and behavior are likely to change before the final release.This preview release is designed to enable the community to experience and review the preliminary designs and direction of key features Windows PowerShell 3.0 and to solicit feedback before features are finalized.
For an interesting post describing what to expect with a CTP, read this very old post from Jeffrey
Travis Jones [MSFT]
Program Manager – Windows PowerShell
Microsoft Corporation -
What’s New In PowerCLI 5.0 – Slides from UK PowerShell UserGroup
Posted on November 22nd, 2011 3 commentsAs promised, here are my slides from this evening’s UK PowerShell UserGroup – What’s New in PowerCLI 5.0.
What’s New in PowerCLI 5.0View more presentations from jonathanmeddsf
-
Working with the HPQ WMI Provider to find NIC Information on HP Proliant Servers
Posted on November 21st, 2011 No commentsI recently had a task to query NIC information on a number of HP Proliant servers, this included the connected NIC speed, duplex settings and status of the configured HP Team. I initally looked at the WMI class Win32_NetworkAdapterConfiguration which contains a lot of info around NIC configuration. Unfortunately, it does not include NIC speed or duplex settings.
Looking for alternatives, I discovered a script from Hugo Peeters which instead queried the registry key HKLM\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318} which looked like it would do the job. However, for some reason this works fine for HP rackmount servers, but blades do not appear to publish NIC info to that registry key so I needed to look for something else.
A colleague pointed me to the HPQ WMI Provider, which I had not seen before and there does not appear to be a lot of published info about either. It can be installed as part of the HP Proliant installation process and adds 800+ classes that can be queried via WMI - a sample is shown below from the Root\HPQ Namespace:
In this instance, I was able to use the following classes to obtain the information I needed:
HP_EthernetTeam
HP_EthernetPort
HP_WinEthLANEndpointThere is an absolute wealth of information stored in here, so I would encourage you to check it out if you work with Windows Server on HP systems. The script I put together puts together a basic report of some key NIC info, with the knowledge that there are never more than 4 NICs in a server being queried.
Note that I have used the parameter -ErrorAction Stop in the WMI queries, to enforce a terminating error to be generated if the WMI query fails. Without this, the error is non-terminating and does not get caught by the Catch statement.
$HP_EthernetTeam = Get-WmiObject -Namespace root\hpq -Class HP_EthernetTeam -ComputerName $ComputerName -ErrorAction Stop
<# .SYNOPSIS Retrieve HP NIC Info from HPQ WMI Namespace .DESCRIPTION Retrieve HP NIC Info from HPQ WMI Namespace .PARAMETER ServersInputFile Path to the file containing server names .PARAMETER OutputFile Path to the csv file to output data to .EXAMPLE PS C:\> Get-HPNICStatus.ps1 -ServersInputFile C:\Scripts\Servers.txt -OutputFile C:\Scripts\HPNICStatus.csv #> [CmdletBinding()] param( [Parameter(Position=0,Mandatory=$true,HelpMessage="Path to the file containing server names")] [System.String] $ServersInputFile, [Parameter(Position=1,Mandatory=$true,HelpMessage="Path to the csv file to output data to")] [System.String] $OutputFile ) $ComputerNames = Get-Content $ServersInputFile # Allow conversion to MB/sec for NIC speed $NICSpeedConversionConstant = 1000000 $myCol = @() foreach ($ComputerName in $ComputerNames){ Write-Host "`n`n" Write-Host "Querying NIC info on $ComputerName" # Test for HPQ WMI Namespace and deal with a failure in catch statement try { $HP_EthernetTeam = Get-WmiObject -Namespace root\hpq -Class HP_EthernetTeam -ComputerName $ComputerName -ErrorAction Stop $HP_EthernetPort = Get-WmiObject -Namespace root\hpq -Class HP_EthernetPort -ComputerName $ComputerName -ErrorAction Stop $HP_WinEthLANEndpoint = Get-WmiObject -Namespace root\hpq -Class HP_WinEthLANEndpoint -ComputerName $ComputerName -ErrorAction Stop Write-Host "Successful query on $ComputerName" # Calculate Team Health Status based on WMI query result switch ($HP_WinEthLANEndpoint.HealthState) { "0" {$HPTeamStatus = "Unknown"; break} "5" {$HPTeamStatus = "OK"; break} "10" {$HPTeamStatus = "Degraded/Warning"; break} "15" {$HPTeamStatus = "Minor Failure"; break} "20" {$HPTeamStatus = "Major Failure"; break} "25" {$HPTeamStatus = "Critical Failure"; break} "30" {$HPTeamStatus = "Non-recoverable Error"; break} default {$HPTeamStatus = "Unknown"} } # Check Ethernet Port Status $EthernetPortHealthStateArray = @() foreach ($EthernetPort in $HP_EthernetPort){ switch ($EthernetPort.HealthState) { "0" {$EthernetPortHealthState = "Unknown"; break} "5" {$EthernetPortHealthState = "OK"; break} "10" {$EthernetPortHealthState = "Degraded/Warning"; break} "15" {$EthernetPortHealthState = "Minor Failure"; break} "20" {$EthernetPortHealthState = "Major Failure"; break} "25" {$EthernetPortHealthState = "Critical Failure"; break} "30" {$EthernetPortHealthState = "Non-recoverable Error"; break} default {$EthernetPortHealthState = "Unknown"} } $EthernetPortHealthStateObject = "" | Select-Object EthernetPortName,EthernetPortHealthStatus $EthernetPortHealthStateObject.EthernetPortName = $EthernetPort.Description $EthernetPortHealthStateObject.EthernetPortHealthStatus = $EthernetPortHealthState $EthernetPortHealthStateArray += $EthernetPortHealthStateObject } $MYObject = “” | Select-Object Servername,HPTeamName,HPTeamStatus,HPTeamSpeed,NIC1Description,NIC1Model,NIC1Speed,NIC1FullDuplex,NIC1HealthState,NIC2Description,NIC2Model,NIC2Speed,NIC2FullDuplex,NIC2HealthState,NIC3Description,NIC3Model,NIC3Speed,NIC3FullDuplex,NIC3HealthState,NIC4Description,NIC4Model,NIC4Speed,NIC4FullDuplex,NIC4HealthState $MYObject.Servername = $ComputerName $MYObject.HPTeamName = $HP_EthernetTeam.Description $MYObject.HPTeamStatus = $HPTeamStatus $MYObject.HPTeamSpeed = [string]($HP_EthernetTeam.Speed / $NICSpeedConversionConstant) + " MB/sec" $MYObject.NIC1Description = $HP_EthernetPort[0].Description $MYObject.NIC1Model = $HP_EthernetPort[0].Caption $MYObject.NIC1Speed = [string]($HP_EthernetPort[0].Speed / $NICSpeedConversionConstant) + " MB/sec" $MYObject.NIC1FullDuplex = $HP_EthernetPort[0].FullDuplex $MYObject.NIC1HealthState = $EthernetPortHealthStateArray[0].EthernetPortHealthStatus $MYObject.NIC2Description = $HP_EthernetPort[1].Description $MYObject.NIC2Model = $HP_EthernetPort[1].Caption $MYObject.NIC2Speed = [string]($HP_EthernetPort[1].Speed / $NICSpeedConversionConstant) + " MB/sec" $MYObject.NIC2FullDuplex = $HP_EthernetPort[1].FullDuplex $MYObject.NIC2HealthState = $EthernetPortHealthStateArray[1].EthernetPortHealthStatus $MYObject.NIC3Description = $HP_EthernetPort[2].Description $MYObject.NIC3Model = $HP_EthernetPort[2].Caption $MYObject.NIC3Speed = if ($HP_EthernetPort[2].Speed -ne $null){[string]($HP_EthernetPort[2].Speed / $NICSpeedConversionConstant) + " MB/sec"} $MYObject.NIC3FullDuplex = $HP_EthernetPort[2].FullDuplex $MYObject.NIC3HealthState = $EthernetPortHealthStateArray[2].EthernetPortHealthStatus $MYObject.NIC4Description = $HP_EthernetPort[3].Description $MYObject.NIC4Model = $HP_EthernetPort[3].Caption $MYObject.NIC4Speed = if ($HP_EthernetPort[3].Speed -ne $null){[string]($HP_EthernetPort[3].Speed / $NICSpeedConversionConstant) + " MB/sec"} $MYObject.NIC4FullDuplex = $HP_EthernetPort[3].FullDuplex $MYObject.NIC4HealthState = $EthernetPortHealthStateArray[3].EthernetPortHealthStatus $myCol += $MYObject } # If WMI query fails catch { Write-Host "Unsuccessful query on $ComputerName" $MYObject = “” | Select-Object Servername,HPTeamName,HPTeamStatus,HPTeamSpeed,NIC1Description,NIC1Model,NIC1Speed,NIC1FullDuplex,NIC1HealthState,NIC2Description,NIC2Model,NIC2Speed,NIC2FullDuplex,NIC2HealthState,NIC3Description,NIC3Model,NIC3Speed,NIC3FullDuplex,NIC3HealthState,NIC4Description,NIC4Model,NIC4Speed,NIC4FullDuplex,NIC4HealthState $MYObject.Servername = $ComputerName $MYObject.HPTeamName = "HPQ WMI is not installed or WMI query failed" $MYObject.HPTeamStatus = "N/A" $MYObject.HPTeamSpeed = "N/A" $MYObject.NIC1Description = "N/A" $MYObject.NIC1Model = "N/A" $MYObject.NIC1Speed = "N/A" $MYObject.NIC1FullDuplex = "N/A" $MYObject.NIC1HealthState = "N/A" $MYObject.NIC2Description = "N/A" $MYObject.NIC2Model = "N/A" $MYObject.NIC2Speed = "N/A" $MYObject.NIC2FullDuplex = "N/A" $MYObject.NIC2HealthState = "N/A" $MYObject.NIC3Description = "N/A" $MYObject.NIC3Model = "N/A" $MYObject.NIC3Speed = "N/A" $MYObject.NIC3FullDuplex = "N/A" $MYObject.NIC3HealthState = "N/A" $MYObject.NIC4Description = "N/A" $MYObject.NIC4Model = "N/A" $MYObject.NIC4Speed = "N/A" $MYObject.NIC4FullDuplex = "N/A" $MYObject.NIC4HealthState = "N/A" $myCol += $MYObject } Clear-Variable HP_EthernetTeam,HP_EthernetPort,HP_WinEthLANEndpoint,HPTeamStatus,EthernetPortHealthStateArray,EthernetPortHealthStateObject,EthernetPortHealthStateArray } $myCol | Export-Csv $OutputFile -NoTypeInformationsdf
HP, powershell, wmi HP, powershell, wmi











