Modifying Explicit Group Membership in SCOM 2012 with PowerShell
This is a continuation of a Data Center Automation series of posts that I have been working on with Anders Bengtsson. Here are the first seven posts in this series:
Creating Management Packs in SCOM 2012 with PowerShell
Creating Performance Collection Rules in SCOM 2012 with PowerShell
Creating Event Based Alerting Rules in SCOM 2012 with PowerShell
Enabling or Disabling Workflows in SCOM 2012 with PowerShell
Deleting Workflows in SCOM 2012 with PowerShell
Creating Groups in SCOM 2012 with PowerShell
Adding References to MPs in SCOM 2012 with PowerShell
*Update v2.0*
Fixed…
- Group membership being modified but not updating during GroupCalc
- When all GUIDs are removed from a group it will not save properly
- When all Membership rules are removed from a group it will not save properly
Improved…
- XML handling
- Error handling
- Script output
- Reference handling
Added support for…
- Computer groups
- Multiple membership rules
- New management packs
- New groups
- Excluded instances (if they are in the UI, then they’ll get added automatically to the any membership rules created by the script)
*Update v2.1*
Improved…
- New group creation and error handling
As of this post this script is not included as an activity in the Operations Manager Admin Integration Pack but will be in the next version. This was a challenging script to write because group modification requires XML manipulation as there are no methods for managing this. I chose to only support explicit membership with this script because that is likely the most common automation need.
Each group discovery can have multiple membership rules which are really only visible by reviewing the XML of the management pack. This script modifies any of these rules, including rules added via the SCOM Console. If the appropriate membership rule does not exist at runtime, then it will be created and members added. If it does exist then it gets the current explicit members, adds any new members passed, and finally removes any members passed. It then replaces the new old list with the new list while keeping any other membership rules not created with this script intact.
Since the plan is to use this in an integration pack it requires that the instances passed to the script be in GUID format and these GUIDs are validated by the script before being added to the group. You can get the GUIDs by using a simple PowerShell command:
Get-SCOMClass –Name ‘Microsoft.Windows.Computer’ | Get-SCOMClassInstance | select name, id
If you notice after running this script that the new members show up in the console under “Explicit Members” but not when you select “View Group Members” then the UI may just not be up to date. Try the following PowerShell command:
(Get-SCOMGroup –DisplayName ‘My Test Group 1’).GetRelatedMonitoringObjects() | select name, path, id
Syntax:
.\ModifyGroupMembership.ps1 –ManagementServer ‘om01.contoso.com’ –ManagementPackID ‘custom.example.test’ –GroupID ‘custom.example.test.group.testgroup1’ –InstancesToAdd ‘8d5e843d-4d4a-3821-91d1-bc6434d6f9f1, aa390a79-b72a-bf58-412b-ebb94a139e06’ –InstancesToRemove ‘732ac45e-4e1a-9369-c9dd-e3b038537474’
Parameters:
Name | Description |
ManagementServer | Name of MS to connect to |
ManagementPackID | ID of the MP you want to create or modify |
GroupID | ID of the group you want to create or modify |
InstancesToAdd | Optional: GUIDs of the instances you want to add to the group. You can pass multiple by separating each with a comma. |
InstancesToRemove | Optional: GUIDs of the instances you want to remove from the group. You can pass multiple by separating each with a comma. |
1 Param(
2 [parameter(Mandatory=$true)]
3 $ManagementServer,
4 [parameter(Mandatory=$true)]
5 $ManagementPackID,
6 [parameter(Mandatory=$true)]
7 $GroupID,
8 $InstancesToAdd,
9 $InstancesToRemove
10 )
11
12 Write-Host "Version 2.0"
13 Write-Host "ManagementServer: "$ManagementServer
14 Write-Host "ManagementPackID: "$ManagementPackID
15 Write-Host "GroupID: "$GroupID
16 Write-Host "InstancesToAdd: "$InstancesToAdd
17 Write-Host "InstancesToRemove: "$InstancesToRemove
18
19 function GetSCOMManagementGroup
20 {
21 param($ms)
22 try
23 {
24 $mg = New-Object Microsoft.EnterpriseManagement.ManagementGroup($ms)
25 }
26 catch
27 {
28 Write-Host "Failed to Connect to SDK, Exiting:"$ms -ForegroundColor Red
29 Write-Host $_.Exception.Message -ForegroundColor Yellow
30 exit
31 }
32 return $mg
33 }
34
35 function GetManagementPackToUpdate
36 {
37 param($mg, $mpID)
38 try
39 {
40 $mp = $mg.GetManagementPacks($mpID)[0]
41 $vIncrement = $mp.Version.ToString().Split('.')
42 $vIncrement[$vIncrement.Length - 1] = ([system.int32]::Parse($vIncrement[$vIncrement.Length - 1]) + 1).ToString()
43 $mp.Version = ([string]::Join(".", $vIncrement))
44 }
45 catch
46 {
47 Write-Host "New MP:"$mpID
48 $mp = CreateManagementPack -mpID $mpID
49 $mg.ImportManagementPack($mp)
50 $mp = GetManagementPack -mg $mg -mpID $mpID
51 }
52 return $mp
53 }
54
55 function GetManagementPack
56 {
57 param ($mg, $mpID)
58 try
59 {
60 $mp = $mg.GetManagementPacks($mpID)[0]
61 }
62 catch
63 {
64 Write-Host "Management Pack Not Found, Exiting:"$mpID -ForegroundColor Red
65 Write-Host $_.Exception.Message -ForegroundColor Yellow
66 exit
67 }
68 return $mp
69 }
70
71 function CreateManagementPack
72 {
73 param($mpID)
74 $mpStore = New-Object Microsoft.EnterpriseManagement.Configuration.IO.ManagementPackFileStore
75 $mp = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPack($mpID, $mpID, (New-Object Version(1, 0, 0)), $mpStore)
76 return $mp
77 }
78
79 function GetReferenceAlias
80 {
81 param($mp, $mpID)
82 if ($mp.Name.ToUpper() -ne $mpID.ToUpper())
83 {
84 $bFound = $false
85 foreach ($ref in $mp.References)
86 {
87 $s = ($ref.Value.ToString().Split("=")[1]).Split(",")[0]
88 if ($s.ToUpper() -eq $mpID.ToUpper())
89 {
90 $bFound = $true
91 $alias = $ref.Key
92 }
93 }
94 if (!($bFound))
95 {
96 Write-Host "MP Reference Not Found, Exiting:"$mpID
97 exit
98 }
99 }
100
101 return $alias
102 }
103
104 function ValidateReference
105 {
106 param($mg, $mp, $mpID)
107 if ($mp.Name.ToUpper() -ne $mpID.ToUpper())
108 {
109 $bFound = $false
110 foreach ($ref in $mp.References)
111 {
112 $s = ($ref.Value.ToString().Split("=")[1]).Split(",")[0]
113 if ($s.ToUpper() -eq $mpID.ToUpper()) {$bFound = $true}
114 }
115 if (!($bFound))
116 {
117 Write-Host "New Reference:"$mpID
118 $mp = CreateReference -mg $mg -mp $mp -mpID $mpID
119 }
120 }
121 return $mp
122 }
123
124 function ValidateReferencesFromInstances
125 {
126 param($mg, $mp, $ht)
127
128 $htClasses = @{}
129 foreach($instance in $ht.GetEnumerator())
130 {
131 try {$htClasses.Add($instance.Value.ToString(),$instance.Value)} catch {}
132 }
133
134 foreach($instance in $htClasses.GetEnumerator())
135 {
136 $classMP = GetClassMPFromMG -mg $mg -criteria ([string]::Format("Name = '{0}'", $instance.Value))
137 $mp = ValidateReference -mg $mg -mp $mp -mpID $classMP.Name
138 }
139
140 return $mp
141 }
142
143 function CreateReference
144 {
145 param($mg, $mp, $mpID)
146 try
147 {
148 $newMP = $mg.GetManagementPacks($mpID)[0]
149 if (!($newMP.sealed))
150 {
151 Write-Host "MP to reference is not sealed, cannot add reference to"$mpID -ForegroundColor Red
152 Write-Host "Exiting" -ForegroundColor Red
153 Write-Host $_.Exception.Message -ForegroundColor Yellow
154 exit
155 }
156 }
157 catch
158 {
159 Write-Host "Referenced MP Not Found in Management Group, Exiting:"$mpID -ForegroundColor Red
160 Write-Host $_.Exception.Message -ForegroundColor Yellow
161 exit
162 }
163
164 $alias = $mpID.Replace(".","")
165 $reference = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackReference($newMP)
166 $mp.References.Add($alias, $reference)
167 return $mp
168 }
169
170 function XMLEncode
171 {
172 param([string]$s)
173 $s = $s.Replace("&", "&")
174 $s = $s.Replace("<", "<")
175 $s = $s.Replace(">", ">")
176 $s = $s.Replace('"', """)
177 $s = $s.Replace("'", "'")
178 return $s.ToString()
179 }
180
181 function ValidateMonitoringObjects
182 {
183 param($guids, $mg)
184 [hashtable]$ht = @{}
185 $guids = $guids.Split(",")
186 foreach ($guid in $guids)
187 {
188 $guid = $guid.Trim()
189 try
190 {
191 $mo = $mg.GetMonitoringObject($guid)
192 try {$ht.Add($guid, ($mo.FullName).Split(":")[0])} catch {}
193 }
194 catch
195 {
196 try {$ht.Add($guid, 'NOTFOUND')} catch {}
197 }
198 }
199 return $ht
200 }
201
202 function GetClassMPFromMG
203 {
204 param($mg, $criteria)
205 $searchCriteria = new-object Microsoft.EnterpriseManagement.Configuration.MonitoringClassCriteria($criteria)
206 $class = ($mg.GetMonitoringClasses($searchCriteria))[0]
207 $mp = $class.GetManagementPack()
208 return $mp
209 }
210
211 function GetRelationshipMPFromMG
212 {
213 param($mg, $criteria)
214 $searchCriteria = new-object Microsoft.EnterpriseManagement.Configuration.MonitoringRelationshipClassCriteria($criteria)
215 $relationship = ($mg.GetMonitoringRelationshipClasses($searchCriteria))[0]
216 $mp = $relationship.GetManagementPack()
217 return $mp
218 }
219
220 function GetMPElementClass
221 {
222 param($mg, $mp, $class)
223
224 $criteria = ([string]::Format("Name = '{0}'", $class))
225 $refMP = GetClassMPFromMG -mg $mg -criteria $criteria
226 $alias = ""
227 if ($refMP.Name -ne $mp.Name)
228 {
229 $alias = (GetReferenceAlias -mp $mp -mpID $refMP.Name) + "!"
230 }
231 $mpElement = '$MPElement[Name="{0}{1}"]$' -f $alias, $class
232
233 return $mpElement
234 }
235
236 function GetMPElementRelationship
237 {
238 param($mg, $mp, $class, $relationship)
239
240 if (($relationship.ToString() -eq 'Microsoft.SystemCenter.ComputerGroupContainsComputer') -and ($class.ToString() -ne 'Microsoft.Windows.Computer'))
241 {
242 $mpName = 'System.Library'
243 $relationship = 'System.ConfigItemContainsConfigItem'
244 }
245 else
246 {
247 $criteria = ([string]::Format("Name = '{0}'", $relationship))
248 $mpName = (GetRelationshipMPFromMG -mg $mg -criteria $criteria).Name
249 }
250
251 $alias = ""
252 if ($mpName -ne $mp.Name)
253 {
254 $alias = (GetReferenceAlias -mp $mp -mpID $mpName) + "!"
255 }
256 $mpElement = '$MPElement[Name="{0}{1}"]$' -f $alias, $relationship
257
258 return $mpElement
259 }
260
261 function GetGroup
262 {
263 param($mg, $mp, $groupID)
264 $group = $mg.GetMonitoringClasses($groupID)[0]
265 if ($group -eq $null)
266 {
267 Write-Host "Group Not Found:"$groupID -ForegroundColor Red
268 $newGroupID = $mp.Name + ($groupID.Split("."))[-1]
269 $group = $mg.GetMonitoringClasses($groupID)[0]
270 if ($group -eq $null)
271 {
272 Write-Host "Group Not Found, Exiting:"$newGroupID -ForegroundColor Red
273 exit
274 }
275 }
276 return $group
277 }
278
279 function ValidateGroup
280 {
281 param($mg, $mp, $groupID)
282 $group = $mg.GetMonitoringClasses($groupID)[0]
283 if ($group -eq $null)
284 {
285 $groupName = ($groupID.Split("."))[-1]
286 $groupID = $groupName
287 $newGroupID = $mp.Name + "." + $groupID
288 Write-Host "New Group:"$newGroupID
289 $mp = CreateGroup -mg $mg -mp $mp -groupID $groupID -groupName $groupName
290 }
291 return $mp
292 }
293
294 function CreateGroup
295 {
296 param($mg, $mp, $groupID, $groupName)
297 $mp = ValidateReference -mg $mg -mp $mp -mpID 'Microsoft.SystemCenter.InstanceGroup.Library'
298 $mp = ValidateReference -mg $mg -mp $mp -mpID 'System.Library'
299 $alias = GetReferenceAlias -mp $mp -mpID 'Microsoft.SystemCenter.InstanceGroup.Library'
300 $systemAlias = GetReferenceAlias -mp $mp -mpID 'System.Library'
301 $formula ='<MembershipRule Comment="Empty Membership Rule">' + `
302 '<MonitoringClass>$MPElement[Name="' + $alias + `
303 '!Microsoft.SystemCenter.InstanceGroup"]$</MonitoringClass>' + `
304 '<RelationshipClass>$MPElement[Name="' + $alias + `
305 '!Microsoft.SystemCenter.InstanceGroupContainsEntities"]$</RelationshipClass>' + `
306 '<Expression>' + `
307 '<SimpleExpression>' + `
308 '<ValueExpression>' + `
309 '<Property>$MPElement[Name="' + $systemAlias + `
310 '!System.Entity"]/DisplayName$' + `
311 '</Property>' + `
312 '</ValueExpression>' + `
313 '<Operator>Equal</Operator>' + `
314 '<ValueExpression>' + `
315 '<Value>False</Value>' + `
316 '</ValueExpression>' + `
317 '</SimpleExpression>' + `
318 '</Expression>' + `
319 '</MembershipRule>'
320
321 $group = New-Object Microsoft.EnterpriseManagement.Monitoring.CustomMonitoringObjectGroup($mp.Name, $groupID, (XMLEncode -s $groupName), $formula)
322 $mp.InsertCustomMonitoringObjectGroup($group)
323 return $mp
324 }
325
326 function CreateEmptyMembershipRule
327 {
328 param($mg, $mp, $relationship, $rules)
329
330 if ($relationship -eq 'Microsoft.SystemCenter.InstanceGroupContainsEntities')
331 {
332 $class = 'Microsoft.SystemCenter.InstanceGroup'
333 }
334 else
335 {
336 $class = 'Microsoft.Windows.Computer'
337 }
338
339 $propertyName = '$MPElement[Name="{0}!System.Entity"]/DisplayName$' -f (GetReferenceAlias -mp $mp -mpID 'System.Library')
340
341 $rulesNode = $rules.SelectSingleNode("/Node1/MembershipRules")
342 $rule = $rules.CreateElement("MembershipRule")
343 [void]$rule.SetAttribute("Comment", "Scripted Membership Rule")
344 [void]$rulesNode.AppendChild($rule)
345
346 $mClass = $rules.CreateElement("MonitoringClass")
347 $mClass.InnerText = (GetMPElementClass -mg $mg -mp $mp -class $class)
348 [void]$rulesNode.MembershipRule.AppendChild($mClass)
349
350 $rClass = $rules.CreateElement("RelationshipClass")
351 $rClass.InnerText = (GetMPElementRelationship -mg $mg -mp $mp -class $class -relationship $relationship)
352 [void]$rulesNode.MembershipRule.AppendChild($rClass)
353
354 $expression = $rules.CreateElement("Expression")
355 [void]$rulesNode.MembershipRule.AppendChild($expression)
356
357 $eNode = $rules.SelectSingleNode("/Node1/MembershipRules/MembershipRule/Expression")
358 $simpleExpression = $rules.CreateElement("SimpleExpression")
359 [void]$eNode.AppendChild($simpleExpression)
360
361 $sNode = $rules.SelectSingleNode("/Node1/MembershipRules/MembershipRule/Expression/SimpleExpression")
362 $valueExpression = $rules.CreateElement("ValueExpression")
363 [void]$sNode.AppendChild($valueExpression)
364
365 $vNode = $rules.SelectSingleNode("/Node1/MembershipRules/MembershipRule/Expression/SimpleExpression/ValueExpression")
366 $property = $rules.CreateElement("Property")
367 $property.InnerText = $propertyName
368 [void]$vNode.AppendChild($property)
369
370 $operator = $rules.CreateElement("Operator")
371 $operator.InnerText = "Equal"
372 [void]$sNode.AppendChild($operator)
373
374 $valueExpression = $rules.CreateElement("ValueExpression")
375 [void]$sNode.AppendChild($valueExpression)
376
377 $vNode = $sNode.ChildNodes[2]
378 $value = $rules.CreateElement("Value")
379 $value.InnerText = "False"
380 [void]$vNode.AppendChild($value)
381
382 return $rules
383 }
384
385 function GetGroupDiscovery
386 {
387 param($group)
388 $groupDiscovery = $group.GetMonitoringDiscoveries()[0]
389 if ($groupDiscovery -eq $null)
390 {
391 Write-Host "Group Discovery Not Found, Exiting" -ForegroundColor Red
392 exit
393 }
394 return $groupDiscovery
395 }
396
397 function GetGroupMembershipRules
398 {
399 param($config)
400 $rulesStart = $config.IndexOf("<MembershipRules>")
401 $rulesEnd = ($config.IndexOf("</MembershipRules>") + 18) - $rulesStart
402 $rules = $config.Substring($rulesStart, $rulesEnd)
403 $rules = '<Node1>' + $rules + '</Node1>'
404 return $rules
405 }
406
407 function GetGroupInstances
408 {
409 param($mg, $mp, $groupID)
410
411 $group = GetGroup -mg $mg -mp $mp -groupID $groupID
412 $discovery = GetGroupDiscovery -group $group
413 $configuration = $discovery.DataSource.Configuration
414 $rules = GetGroupMembershipRules -config $configuration
415 $xPath = "/Node1/MembershipRules/MembershipRule/IncludeList/MonitoringObjectId"
416 $guids = Select-Xml -Content $rules -XPath $xPath
417 $existingInstances = @{}
418
419 foreach($instance in $guids)
420 {
421 try {$existingInstances.Add($instance.ToString(),$instance)} catch {}
422 }
423
424 return $existingInstances
425 }
426
427 function UpdateGroup
428 {
429 param($mg, $mp, $groupID, $instancesToAdd, $instancesToRemove)
430
431 $existingInstances = GetGroupInstances -mg $mg -mp $mp -groupID $groupID
432
433 if ($instancesToAdd -ne $null){$instancesToAdd = ValidateMonitoringObjects -guids $instancesToAdd -mg $mg}
434 else {$instancesToAdd = @{}}
435
436 $instancesToAdd = RemoveEntriesFromHashTable -guids $instancesToRemove -existingInstances $existingInstances -ht $instancesToAdd
437 $mp = ValidateReferencesFromInstances -mg $mg -mp $mp -ht $instancesToAdd
438
439 Write-Host "Update MP:"$mp.Name
440 $mp.AcceptChanges()
441 $mp = GetUpdatedGroupDiscovery -mg $mg -mp $mp -groupID $groupID -instancesToAdd $instancesToAdd -instancesToRemove $instancesToRemove
442
443 return $mp
444 }
445
446 function GetUpdatedGroupDiscovery
447 {
448 param($mg, $mp, $groupID, $instancesToAdd, $instancesToRemove)
449 $group = GetGroup -mg $mg -mp $mp -groupID $groupID
450 $discovery = GetGroupDiscovery -group $group
451 $configuration = $discovery.DataSource.Configuration
452 $relationship = GetRelationshipType -mg $mg -discovery $discovery
453 [xml]$rules = GetGroupMembershipRules -config $configuration
454 $exclusions = GetExclusions -rules $rules
455
456 foreach($instance in $instancesToAdd.GetEnumerator())
457 {
458 $rules = AddGUIDToDiscovery -guid $instance.Key.ToString() -mg $mg -mp $mp -class $instance.Value.ToString() -rules $rules -exclusions $exclusions -relationship $relationship
459 }
460
461 if ($instancesToRemove -ne $null)
462 {
463 foreach($instance in $instancesToRemove.Split(","))
464 {
465 Write-Host "Delete GUID:"$instance
466 $rules = RemoveGUIDFromDiscovery -guid $instance.Trim() -rules $rules
467 }
468
469 $rules = DeleteEmptyIncludeNodes -mg $mg -mp $mp -rules $rules -relationship $relationship
470 }
471
472 $configuration = CleanUpDiscoveryConfiguration -configuration $configuration -rules $rules
473
474 $discovery.Status = [Microsoft.EnterpriseManagement.Configuration.ManagementPackElementStatus]::PendingUpdate
475 $discovery.DataSource.Configuration = $configuration.ToString().Trim()
476 $mp = $discovery.GetManagementPack()
477 Write-Host "Update MP:"$mp.Name
478 [void]$mp.AcceptChanges()
479 [void]$mg.RefreshMonitoringGroupMembers($mp)
480
481 return $mp
482 }
483
484 function DeleteEmptyIncludeNodes
485 {
486 param($mg, $mp, $relationship, $rules)
487 $xPath = "/Node1/MembershipRules/MembershipRule"
488 $nodes = $rules.SelectNodes($xPath)
489
490 foreach ($node in $nodes)
491 {
492 if (($node.IncludeList.ChildNodes.Count -eq 0) -and ($node.IncludeList.MonitoringObjectId.Count -eq 0))
493 {
494 if ((($node.SelectSingleNode("Expression")).Name -eq 'Expression') -and (($node.SelectSingleNode("IncludeList")).Name -eq 'IncludeList'))
495 {
496 [void]$node.RemoveChild($node.SelectSingleNode("IncludeList"))
497 }
498 elseif (($node.SelectSingleNode("IncludeList")).Name -eq 'IncludeList')
499 {
500 [void]$node.ParentNode.RemoveChild($node)
501 }
502 }
503 }
504
505 if ($rules.SelectNodes($xPath).Count -eq 0)
506 {
507 $rules = CreateEmptyMembershipRule -mg $mg -mp $mp -relationship $relationship -rules $rules
508 }
509
510 return $rules
511 }
512
513 function CleanUpDiscoveryConfiguration
514 {
515 param($configuration, $rules)
516
517 $newRules = ($rules.OuterXml).Replace("<Node1>", "").Replace("</Node1>", "")
518 $i = $configuration.IndexOf("<MembershipRules>")
519 [string]$configuration = $configuration.SubString(0, $i) + $newRules
520
521 return $configuration
522 }
523
524 function GetRelationshipType
525 {
526 param($mg, $discovery)
527 $id = ($discovery.DiscoveryRelationshipCollection[0].TypeID).ToString().Split("=")[1]
528 $criteria = ([string]::Format("Id = '{0}'", $id))
529 $searchCriteria = new-object Microsoft.EnterpriseManagement.Configuration.MonitoringRelationshipClassCriteria($criteria)
530 $relationship = ($mg.GetMonitoringRelationshipClasses($searchCriteria))[0]
531 return $relationship
532 }
533
534 function GetExclusions
535 {
536 param($rules)
537 $xPath = "/Node1/MembershipRules/MembershipRule/ExcludeList/MonitoringObjectId"
538 $guids = $rules.SelectNodes($xPath)
539 $exclusions = @{}
540
541 foreach($instance in $guids)
542 {
543 try {$exclusions.Add($instance.InnerText.ToString(),$instance.InnerText.ToString())} catch {}
544 }
545
546 return $exclusions
547 }
548
549 function AddGUIDToDiscovery
550 {
551 param($mg, $mp, $guid, $class, $rules, $exclusions, $relationship)
552
553 $guids = GetIncludedGUIDS -rules $rules
554
555 if (!($guids.Contains($guid)))
556 {
557 $classes = GetMembershipRuleMonitoringClasses -rules $rules
558 Write-Host "New GUID:"$guid":"$class
559 if ($classes.ContainsKey($class.ToString()))
560 {
561 $rules = AddIncludeGUID -rules $rules -guid $guid -class $classes.Get_Item($class.ToString())
562 }
563 else
564 {
565 Write-Host "New Membership Rule:"$class
566 $rules = CreateNewMembershipRule -mg $mg -mp $mp -rules $rules -guid $guid -class $class -exclusions $exclusions -relationship $relationship
567 }
568 }
569
570 return $rules
571 }
572
573 function CreateNewMembershipRule
574 {
575 param($mg, $mp, $guid, $class, $rules, $exclusions, $relationship)
576
577 [xml]$xml = $rules
578
579 $rulesNode = $xml.SelectSingleNode("/Node1/MembershipRules")
580 $rule = $xml.CreateElement("MembershipRule")
581 [void]$rule.SetAttribute("Comment", "Scripted Membership Rule")
582 [void]$rulesNode.AppendChild($rule)
583
584 $mClass = $xml.CreateElement("MonitoringClass")
585 $mClass.InnerText = (GetMPElementClass -mg $mg -mp $mp -class $class)
586 [void]$rulesNode.MembershipRule.AppendChild($mClass)
587
588 $rClass = $xml.CreateElement("RelationshipClass")
589 $rClass.InnerText = (GetMPElementRelationship -mg $mg -mp $mp -class $class -relationship $relationship)
590 [void]$rulesNode.MembershipRule.AppendChild($rClass)
591
592 $iList = $xml.CreateElement("IncludeList")
593 [void]$rulesNode.MembershipRule.AppendChild($iList)
594
595 $count = ($rulesNode.ChildNodes.Count) - 1
596 $includeNode = $rulesNode.ChildNodes[$count].ChildNodes[2]
597 $mObjectId = $xml.CreateElement("MonitoringObjectId")
598 $mObjectId.InnerText = $guid.Trim()
599 [void]$includeNode.AppendChild($mObjectId)
600
601 if ($exclusions.Count -gt 0)
602 {
603 $eList = $xml.CreateElement("ExcludeList")
604 [void]$rulesNode.MembershipRule.AppendChild($eList)
605
606 foreach ($guid in $exclusions.GetEnumerator())
607 {
608 $excludeNode = $rulesNode.ChildNodes[$count].ChildNodes[3]
609 $mObjectId = $xml.CreateElement("MonitoringObjectId")
610 $mObjectId.InnerText = $guid.Value.ToString().Trim()
611 [void]$excludeNode.AppendChild($mObjectId)
612 }
613 }
614
615 return $xml
616 }
617
618 function AddIncludeGUID
619 {
620 param($guid, $class, $rules)
621
622 [xml]$xml = $rules
623 $xPath = "/Node1/MembershipRules/MembershipRule"
624 $ruleNodes = $xml.SelectNodes($xPath)
625
626 foreach ($rule in $ruleNodes)
627 {
628 $className = ($rule.Get_InnerXML()).Split('"')[1]
629 if ($className -eq $class)
630 {
631 $includeNode = $rule.SelectSingleNode("IncludeList")
632 if ($includeNode -ne $null)
633 {
634 $child = $xml.CreateElement("MonitoringObjectId")
635 $child.InnerText = $guid
636 [void]$includeNode.AppendChild($child)
637 break
638 }
639 }
640 }
641
642 return $xml
643 }
644
645 function GetMembershipRuleMonitoringClasses
646 {
647 param($rules)
648
649 [xml]$xml = $rules
650 $xPath = "/Node1/MembershipRules/MembershipRule"
651 $ruleNodes = $xml.SelectNodes($xPath)
652 $ht = @{}
653
654 foreach ($rule in $ruleNodes)
655 {
656 $includeNode = $rule.SelectSingleNode("IncludeList")
657 if ($includeNode -ne $null)
658 {
659 $fullPath = ($rule.Get_InnerXML()).Split('"')[1]
660 $class = $fullPath.Split("!")[1]
661 try { $ht.Add($class.ToString(), $fullPath) } catch {}
662 }
663 }
664
665 return $ht
666 }
667
668 function GetIncludedGUIDs
669 {
670 param($rules)
671 $xPath = "/Node1/MembershipRules/MembershipRule/IncludeList/MonitoringObjectId"
672 $guids = $guids = $rules.SelectNodes($xPath)
673 $ht = @{}
674 foreach ($g in $guids) { try { $ht.Add($g.InnerText.ToString(), $g.InnerText.ToString()) } catch {} }
675 return $ht
676 }
677
678 function RemoveGUIDFromDiscovery
679 {
680 param($guid, $rules)
681 $xPath = "/Node1/MembershipRules/MembershipRule/IncludeList[MonitoringObjectId='{0}']/MonitoringObjectId" -f $guid.ToString()
682 $guids = $rules.SelectNodes($xPath)
683
684 foreach ($g in $guids)
685 {
686 if ($g.InnerText -eq $guid.ToString())
687 {
688 [void]$g.ParentNode.RemoveChild($g)
689 }
690 }
691
692 return $rules
693 }
694
695 function RemoveEntriesFromHashTable
696 {
697 param($guids, $existingInstances, $ht)
698 if ($guids -ne $null)
699 {
700 $guids = $guids.Split(",")
701 foreach ($guid in $guids)
702 {
703 $guid = $guid.Trim()
704 try
705 {
706 $ht.Remove($guid)
707 }
708 catch {}
709 }
710 }
711
712 foreach ($guid in $existingInstances.GetEnumerator())
713 {
714 if ($ht.ContainsKey($guid.Key.ToString()))
715 {
716 $ht.Remove($guid.Key.ToString())
717 }
718 }
719 return $ht
720 }
721
722 try { Import-Module OperationsManager } catch
723 {
724 Write-Host "SCOM Module Not Found, Exiting" -ForegroundColor Red
725 Write-Host $_.Exception.Message -ForegroundColor Yellow
726 exit
727 }
728
729 $MG = GetSCOMManagementGroup -ms $ManagementServer
730 $MP = GetManagementPackToUpdate -mg $MG -mpID $ManagementPackID
731 $MP = ValidateGroup -mg $MG -mp $MP -groupID $GroupID
732 $MP = UpdateGroup -mg $MG -mp $MP -groupID $GroupID -instancesToAdd $InstancesToAdd -instancesToRemove $InstancesToRemove
733
734 Write-Host "Script Complete"