Public/New-SCOMComputerGroup.ps1
|
Function New-SCOMComputerGroup { <# .DESCRIPTION Will create an instance group containing Windows Computers [Microsoft.Windows.Computer] objects and optionally include related Health Service Watchers [Microsoft.SystemCenter.HealthServiceWatcher]. .EXAMPLE "ms01.contoso.com","db01.contoso.com" | New-SCOMComputerGroup -MPName "Accounting Team Computer/HSW Group 2020" -NameSpace "Accounting" -Verbose .EXAMPLE $FQDNs = (Get-SCOMAgent | Where-Object Name -like "*DB*").Name New-SCOMComputerGroup -MPName "My Database Computers-HSW Group" -ComputerName $FQDNs -NameSpace "DBSERVERS" -AddHealthServiceWatchers -Verbose -PassThru The above example will get all agent names which match the pattern and add the Computer objects as well as the corresponding Health Service Watcher objects. .INPUTS Accepts array of computer FQDN names (fully qualified domain name) .OUTPUTS SCOM Management Pack [Microsoft.EnterpriseManagement.Configuration.ManagementPack] .NOTES Script: New-SCOMComputerGroup Author: Tyson Paul (https://monitoringguys.com/2019/11/12/scomhelper/) Version History: 2020.08.18.1333 - Added MP and Group display name parameters 2020.08.11.1309 - Polished a bit. HSW objects are optional. 2020.06.17 - v1.0 #> [CmdletBinding(DefaultParameterSetName='Parameter Set 1', SupportsShouldProcess=$false, PositionalBinding=$false, HelpUri = 'http://www.microsoft.com/', ConfirmImpact='Medium')] [Alias()] [OutputType([Microsoft.EnterpriseManagement.Configuration.ManagementPack])] Param ( # New MP custom name [Parameter(Mandatory=$false, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, ParameterSetName='Parameter Set 1')] [string]$MPName='', # New MP custom DISPLAY name [Parameter(Mandatory=$false, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, ParameterSetName='Parameter Set 1')] [string]$MPDisplayName='', # Name of computer to be added to the group (and associated Health Service Watcher instance) [Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, ParameterSetName='Parameter Set 1')] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string[]]$ComputerName, # Name of mgmt server to use for SDK connection [Parameter(Mandatory=$false, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, ParameterSetName='Parameter Set 1')] [string]$MgmtServerName, [Parameter(Mandatory=$false, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, ParameterSetName='Parameter Set 1')] [string]$GroupName, [Parameter(Mandatory=$false, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, ParameterSetName='Parameter Set 1')] [string]$GroupDisplayName, # Namespace for group name. Example: "Lab" or "Accounting". This will affect only the hidden/ugly element "ID" in the MP. [Parameter(Mandatory=$false, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, ParameterSetName='Parameter Set 1')] [string]$NameSpace = "GROUP", # This will include corresponding Health Service Watcher objects in the group. [Parameter(Mandatory=$false, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, ParameterSetName='Parameter Set 1')] [switch]$AddHealthServiceWatchers, # This will return the new [Microsoft.EnterpriseManagement.Configuration.ManagementPack] object. [Parameter(Mandatory=$false, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, ParameterSetName='Parameter Set 1')] [switch]$PassThru ) Begin { ###################################### FUNCTIONS ####################################################### ######################################################################################################## Function Build-RefString { Param ( $MP ) Return ("$($MP.Name)$($MP.version.tostring())".Replace('.','')) } ######################################################################################################## Function Clean-DisplayName { [OutputType([String])] Param( # Param1 help description [Parameter(Mandatory=$false, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=0, ParameterSetName='Parameter Set 1')] [string]$Name='' ) Begin{} Process{ Return ($Name -replace '[^a-zA-Z0-9. \-()]', '') } End {} } ######################################################################################################## Function Clean-ID { [OutputType([String])] Param( # Param1 help description [Parameter(Mandatory=$false, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=0, ParameterSetName='Parameter Set 1')] [string]$Name='' ) Begin{} Process{ $tmp = $Name.Replace(' ','.').Replace('..','.').Replace('..','.') $tmp2 = ( ($tmp -replace '[^a-zA-Z0-9.]', '').Replace('..','.').Replace('..','.') ) Return $tmp2 } End{} } ######################################################################################################## Function _LINE_ { $MyInvocation.ScriptLineNumber } ######################################################################################################## ######################################################################################################## Function Connect-MgmtGroup { # Connect to SCOM mgmt group Try{ $MG = Get-SCOMManagementGroup -ErrorAction Stop -Verbose:$VerbosePreference If (-NOT $MG ) { Write-Verbose "No SCOMManagementGroupConnection" Throw } ElseIf($MgmtServerName) { If ($MG.ConnectionSettings.ServerName -ne $MgmtServerName){ Write-Verbose "Existing MG connection, wrong server: [$($MG.ConnectionSettings.ServerName)]. Establish connection to new server: [$($MgmtServerName)]..." Throw } } } Catch { Try { $MG = Connect-OMManagementGroup -SDK $MgmtServerName If (-NOT $MG) { Throw "No SCOMManagementGroupConnection" } }Catch { Write-Error "$(_LINE_): Unable to establish connection to designated mgmt server: [$($MgmtServerName)]. Exiting." Exit } } } ######################################################################################################## $DateStamp = (Get-Date -f "yyyyMMdd.hhmmss") # Clean names to remove invalid characters $CleanMPDisplayName = Clean-DisplayName -Name $MPDisplayName $CleanMPID = Clean-ID -Name $MPName If (-NOT $CleanMPID) { $CleanMPID = Clean-ID -Name $CleanMPDisplayName } If (-NOT $CleanMPID) { Write-Error "No valid MPName provided. Exiting." Return } # Will try to accomodate both group Name and DisplayName If ($GroupDisplayName) { Write-Verbose "Group DisplayName provided. Will attempt to clean it..." $GroupDisplayName = $GroupDisplayName | Clean-DisplayName } $CleanGroupID = $GroupName | Clean-ID If (-NOT $CleanGroupID) { Write-Verbose "No valid GroupName. Attempt to use cleaned group DisplayName (if provided)..." $CleanGroupID = $GroupDisplayName | Clean-ID } If (-NOT $CleanGroupID) { $CleanGroupID = "$($CleanMPID).$($DateStamp).Group" Write-Verbose "No valid GroupName. Will use default group naming: [$($CleanGroupID)]" } Write-Verbose @" New MP DisplayName provided by user:[$MPName] DisplayName after being sanitized:[$($CleanMPDisplayName)] MPID after being sanitized:[$($CleanMPID)]] "@ Write-Verbose "Attempt import of OperationsManager module" . Import-SCOMPowerShellModule Write-Verbose "Verify mgmt group connection..." . Connect-MgmtGroup Write-Verbose "Get necessary MP objects for building group definitions..." $Formula = '' # Get the necessary reference MPs $LibMp = Get-SCOMManagementPack -Name Microsoft.Windows.Library $InsMp = Get-SCOMManagementPack -Name Microsoft.SystemCenter.InstanceGroup.Library $SCmp = Get-SCOMManagementPack -Name Microsoft.SystemCenter.Library # Build the alias Strings $Libalias = Build-RefString -MP $LibMp $InsAlias = Build-RefString -MP $InsMp $SCAlias = Build-RefString -MP $SCmp # Check if the MP already exists if not we will create it $MPAlreadyExists = Get-SCOMManagementPack -Name $CleanMPID If($MPAlreadyExists) { Throw @" Error: Management pack with name [$($MPName)] already exists. New MP DisplayName provided by user:[$MPName] DisplayName after being sanitized:[$($CleanMPDisplayName)] MPID after being sanitized:[$($CleanMPID)]] "@ Try {$MG.Dispose()}Catch{<#Tidy up#>} Exit } [System.Collections.ArrayList]$arrWinComp = @() [System.Collections.ArrayList]$arrHSW = @() $WinCompClass = Get-SCOMClass -Name "Microsoft.Windows.Computer" $HSWClass = Get-SCOMClass -Name "Microsoft.SystemCenter.HealthServiceWatcher" }#end Begin Process { # Create collection of Computers and HSW objects ForEach ($CName in $ComputerName) { $WinComp = $NULL $Criteria = "DisplayName = '$CName'" $objCriteria = New-Object Microsoft.EnterpriseManagement.Monitoring.MonitoringObjectCriteria($Criteria ,$WinCompClass) $WinComp = $MG.GetMonitoringObjects($objCriteria) If (-NOT $WinComp) { Write-Warning "Computer: [$($CName)] not found! Verify that the fully qualified domain name exists." Continue } $CompID = $WinComp.Id.Guid Write-Verbose "Found Computer:`t[$($CName)], [$($CompID)]" $Null = $arrWinComp.Add(" <MonitoringObjectId>$CompID</MonitoringObjectId>") If ($AddHealthServiceWatchers) { $objCriteria = New-Object Microsoft.EnterpriseManagement.Monitoring.MonitoringObjectCriteria($Criteria ,$HSWClass) $HSW = $MG.GetMonitoringObjects($objCriteria) $WatchID = $HSW.Id.Guid Write-Verbose "Found HSW:`t`t[$($CName)], [$($WatchID)]" $Null = $arrHSW.Add(" <MonitoringObjectId>$WatchID</MonitoringObjectId>") } } }#end Process End { # Add Windows Computer GUIDs to explicit membership rule $Formula += @" <MembershipRule> <MonitoringClass>`$MPElement[Name="$($Libalias)!Microsoft.Windows.Server.Computer"]`$</MonitoringClass> <RelationshipClass>`$MPElement[Name="$($InsAlias)!Microsoft.SystemCenter.InstanceGroupContainsEntities"]`$</RelationshipClass> <IncludeList> $arrWinComp </IncludeList> </MembershipRule> "@ # Add HSW GUIDs to explicit membership rule, if appropriate If ($AddHealthServiceWatchers) { $Formula += @" <MembershipRule> <MonitoringClass>`$MPElement[Name="$($SCAlias)!Microsoft.SystemCenter.HealthServiceWatcher"]`$</MonitoringClass> <RelationshipClass>`$MPElement[Name="$($InsAlias)!Microsoft.SystemCenter.InstanceGroupContainsEntities"]`$</RelationshipClass> <IncludeList> $arrHSW </IncludeList> </MembershipRule> "@ } $store = New-Object Microsoft.EnterpriseManagement.Configuration.IO.ManagementPackFileStore # Create the MP Object Write-Verbose "Create new MP object (virtual)..." $MP = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPack($CleanMPID, $CleanMPID, (New-Object Version(1, 0, 0)), $store) # Set the MP Display Name $MP.DisplayName = $CleanMPDisplayName # Add MP references Write-Verbose "Add references to MP object..." $LibRef = New-object Microsoft.EnterpriseManagement.Configuration.ManagementPackReference($MP, $LibMp.Name, $LibMp.KeyToken, $LibMp.Version) $InsRef = New-object Microsoft.EnterpriseManagement.Configuration.ManagementPackReference($MP, $InsMp.Name, $InsMp.KeyToken, $InsMp.Version) $SCRef = New-object Microsoft.EnterpriseManagement.Configuration.ManagementPackReference($MP, $SCmp.Name, $SCmp.KeyToken, $SCmp.Version) $MP.References.Add($Libalias,$LibRef) $MP.References.Add($InsAlias,$InsRef) $MP.References.Add($SCAlias,$SCRef) Try { # Save Changes $MP.AcceptChanges() Write-Verbose "MP object was verified successfully." } Catch { Throw "Failed to verify new MP content.`nError:$($_)`nExiting." Try {$MG.Dispose()}Catch{<#Tidy up#>} Exit } Try { # Import MP Write-Verbose "Importing new empty MP into management group: [$($MG.Name)]..." $MG.ImportManagementPack($mp) } Catch { Throw "Failed to import new MP.`nError:$($_)`nExiting." Try {$MG.Dispose()}Catch{<#Tidy up#>} Exit } #TYSON $GroupID = "$($CleanMPID).Group" $GroupID = "$($CleanGroupID)" If ($GroupID -notmatch 'group$') { $GroupID = "$($GroupID).Group" } # Create Group Object and try to insert it into the MP. Write-Verbose "Create new group object: [$($GroupID)]..." $group = New-Object Microsoft.EnterpriseManagement.Monitoring.CustomMonitoringObjectGroup($NameSpace, $GroupID, $CleanMPID, $Formula) If ($GroupDisplayName) { $group.DisplayName = $GroupDisplayName } Try{ Write-Verbose "Inserting new Group formula into MP..." $MP.InsertCustomMonitoringObjectGroup($Group) Write-Verbose "Success!" } Catch{ Throw "Failed to add group formula to MP.`nError:$($_)`nExiting." Try {$MG.Dispose()}Catch{<#Try to tidy up#>} Exit } # Finally, get the new pack If ($PassThru) { Get-SCOMManagementPack -Name $CleanMPID } }#end End } |