There will be times that we want to make changes to our agent configuration, and often times a script is the simplest way to do this on a large number of agents. Perhaps we want to add an additional management group to the agent, or enable/disable Active directory integration?
The most common scenario will be when multi-homing agents in a side by side SCOM 2007 to SCOM 2012 migration, to have an automated way to remove the old SCOM 2007 management group.
The agent configuration objects are documented here: http://msdn.microsoft.com/en-us/library/hh328967.aspx
ManagementServiceConfigurationClass.AddManagementGroup
This method adds a new, but inactive, management group to the agent.
ManagementServiceConfigurationClass.DisableActiveDirectoryIntegration
This method prevents an agent from querying Active Directory or Active Directory Domain Services (AD DS) for the list of the management groups in which this agent participates.
ManagementServiceConfigurationClass.EnableActiveDirectoryIntegration
This method allows an agent to query Active Directory or AD DS for the list of the management groups in which this agent participates.
ManagementServiceConfigurationClass.GetActiveDirectoryIntegrationEnabled
This method returns a Boolean value indicating whether or not true Active Directory integration is enabled for the agent.
ManagementServiceConfigurationClass.GetManagementGroup
This method returns a ManagementServiceConfigurationClass Object object.
ManagementServiceConfigurationClass.GetManagementGroups
This method returns a ManagementGroupCollectionClass Object object.
ManagementServiceConfigurationClass.ReloadConfiguration
This method reloads the updated agent configuration.ManagementServiceConfigurationClass.RemoveManagementGroup
This method removes an active management group from the agent.
ManagementServiceConfigurationClass.UpdateActionAccount
This method updates the existing action account for a given management group with the given account.
Here are some code examples that run in VBScript. I choose VBscript because not all agent managed machines will have PowerShell installed (Server 2003, and 2008 by default).
Add a management group to an existing agent
Option Explicit Dim objMSConfig Set objMSConfig = CreateObject("AgentConfigManager.MgmtSvcCfg") ' Add a management group Call objMSConfig.AddManagementGroup ("ManagementGroupName", "ManagementServer.domain.com",5723)
Add a management group to an existing agent, and initiate a restart of the agent to immediately accept the changes
Option Explicit Dim objMSConfig Set objMSConfig = CreateObject("AgentConfigManager.MgmtSvcCfg") ' Add a management group Call objMSConfig.AddManagementGroup ("ManagementGroupName", "ManagementServer.domain.com",5723) Call objMSConfig.ReloadConfiguration
Remove a management group from an agent, and restart
Option Explicit Dim objMSConfig Set objMSConfig = CreateObject("AgentConfigManager.MgmtSvcCfg") ' Remove a management group Call objMSConfig.RemoveManagementGroup ("ManagementGroupName") Call objMSConfig.ReloadConfiguration
Disable AD Integration on an agent (then restart) which will delete all AD integrated management groups from the agent.
Option Explicit Dim objMSConfig Set objMSConfig = CreateObject("AgentConfigManager.MgmtSvcCfg") ' Disable AD Integration Call objMSConfig.DisableActiveDirectoryIntegration() Call objMSConfig.ReloadConfiguration
You can get pretty fancy with your scripts – to add error detection, if/then, to make a lot of actions in one push. Here is an example written by Joe Thompson, from http://www.systemcentercentral.com/forums-archive/topic/deploying-scom-2012-agents-using-sccm-2012/
I will insert his code example directly here:
Option Explicit On Error Resume Next Dim objMSConfig, objMG, isChange isChange = 0 Set objMSConfig = CreateObject(“AgentConfigManager.MgmtSvcCfg”) If Err <> 0 Then wscript.echo “Agent not installed or extension error!” wscript.quit(Err) End if 'See if Mgmt Group exists Set objMG = objMSConfig.GetManagementGroup (“MYNEWMG”) If Err <> 0 Then ‘New Mgmt not set. ’Add a management group Call objMSConfig.AddManagementGroup (“MYNEWMG”, “mymanagementserver.contoso.com”,5723) objMSConfig.ReloadConfiguration isChange = isChange + 1 End If WSCript.Sleep 15000 ‘Remove a management group if it exists Set objMG = objMSConfig.GetManagementGroup (“MYOLDMG”) If Err = 0 Then Call objMSConfig.RemoveManagementGroup (“MYOLDMG”) objMSConfig.ReloadConfiguration isChange = isChange + 1 End If Wscript.Echo “Compliant” WScript.Quit
There are also good samples on how to make a SCOM task with a script like this – to add or remove management groups straight from your existing SCOM deployment: http://scomandplus.blogspot.com/2012/07/adding-scom-agent-task-to-update.html
Wrapping it up in a management pack:
I am going to use all of this above – to create a management pack. The purpose of this MP will be to discover which agents are multi-homed, and then provide an agent based task in the new management group – to remove the old management group.
I will start with a simple class and discovery, which will discover any healthservice that has an HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Agent Management Groups key.
Next, I will create a monitor, that will look for the existence of a Registry Key, which I wrote about here: https://kevinholman.com/2010/07/28/how-to-create-a-monitor-for-existence-of-a-registry-key/ We can use this to detect the existence of the unwanted management group.
Last, we will create a task, and target it to our new class.
Here is the XML of the MP. It is very simple… a class (based on Local Application) with a simple registry discovery that should discover all agents. Then a monitor to inspect for your “old” management group. Then a console task (which will show up when you look at the state view included) to remove the management group (this is hard coded to my test MG name, but you just need to edit the script to change it).
<ManagementPack ContentReadable="true" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <Manifest> <Identity> <ID>Example.SCOMMigration</ID> <Version>1.0.0.9</Version> </Identity> <Name>Example.SCOMMigration</Name> <References> <Reference Alias="SC"> <ID>Microsoft.SystemCenter.Library</ID> <Version>6.1.7221.0</Version> <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> </Reference> <Reference Alias="Windows"> <ID>Microsoft.Windows.Library</ID> <Version>6.1.7221.0</Version> <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> </Reference> <Reference Alias="Health"> <ID>System.Health.Library</ID> <Version>6.1.7221.0</Version> <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> </Reference> <Reference Alias="System"> <ID>System.Library</ID> <Version>6.1.7221.0</Version> <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> </Reference> </References> </Manifest> <TypeDefinitions> <EntityTypes> <ClassTypes> <ClassType ID="Example.SCOMMigration.OldMG" Accessibility="Internal" Abstract="false" Base="Windows!Microsoft.Windows.LocalApplication" Hosted="true" Singleton="false" /> </ClassTypes> </EntityTypes> <MonitorTypes> <UnitMonitorType ID="Example.SCOMMigration.OldMGExists.MonitorType" Accessibility="Internal"> <MonitorTypeStates> <MonitorTypeState ID="RegKeyExists" NoDetection="false" /> <MonitorTypeState ID="RegKeyMissing" NoDetection="false" /> </MonitorTypeStates> <Configuration /> <MonitorImplementation> <MemberModules> <DataSource ID="RegDS" TypeID="Windows!Microsoft.Windows.RegistryProvider"> <ComputerName>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</ComputerName> <RegistryAttributeDefinitions> <RegistryAttributeDefinition> <AttributeName>OldMGExists</AttributeName> <Path>SYSTEM\CurrentControlSet\Services\HealthService\Parameters\Management Groups\OMMG</Path> <PathType>0</PathType> <AttributeType>0</AttributeType> </RegistryAttributeDefinition> </RegistryAttributeDefinitions> <Frequency>60</Frequency> </DataSource> <ConditionDetection ID="CDExists" TypeID="System!System.ExpressionFilter"> <Expression> <SimpleExpression> <ValueExpression> <XPathQuery Type="String">Values/OldMGExists</XPathQuery> </ValueExpression> <Operator>Equal</Operator> <ValueExpression> <Value Type="String">true</Value> </ValueExpression> </SimpleExpression> </Expression> </ConditionDetection> <ConditionDetection ID="CDMissing" TypeID="System!System.ExpressionFilter"> <Expression> <SimpleExpression> <ValueExpression> <XPathQuery Type="String">Values/OldMGExists</XPathQuery> </ValueExpression> <Operator>Equal</Operator> <ValueExpression> <Value Type="String">false</Value> </ValueExpression> </SimpleExpression> </Expression> </ConditionDetection> </MemberModules> <RegularDetections> <RegularDetection MonitorTypeStateID="RegKeyExists"> <Node ID="CDExists"> <Node ID="RegDS" /> </Node> </RegularDetection> <RegularDetection MonitorTypeStateID="RegKeyMissing"> <Node ID="CDMissing"> <Node ID="RegDS" /> </Node> </RegularDetection> </RegularDetections> </MonitorImplementation> </UnitMonitorType> </MonitorTypes> </TypeDefinitions> <Monitoring> <Discoveries> <Discovery ID="Example.SCOMMigration.OldMGDiscovery" Enabled="true" Target="Windows!Microsoft.Windows.Server.OperatingSystem" ConfirmDelivery="false" Remotable="true" Priority="Normal"> <Category>Discovery</Category> <DiscoveryTypes> <DiscoveryClass TypeID="Example.SCOMMigration.OldMG" /> </DiscoveryTypes> <DataSource ID="DS" TypeID="Windows!Microsoft.Windows.FilteredRegistryDiscoveryProvider"> <ComputerName>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</ComputerName> <RegistryAttributeDefinitions> <RegistryAttributeDefinition> <AttributeName>AgentRegExists</AttributeName> <Path>SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Agent Management Groups</Path> <PathType>0</PathType> <AttributeType>0</AttributeType> </RegistryAttributeDefinition> </RegistryAttributeDefinitions> <Frequency>3600</Frequency> <ClassId>$MPElement[Name="Example.SCOMMigration.OldMG"]$</ClassId> <InstanceSettings> <Settings> <Setting> <Name>$MPElement[Name="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Name> <Value>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value> </Setting> <Setting> <Name>$MPElement[Name="System!System.Entity"]/DisplayName$</Name> <Value>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</Value> </Setting> </Settings> </InstanceSettings> <Expression> <SimpleExpression> <ValueExpression> <XPathQuery Type="String">Values/AgentRegExists</XPathQuery> </ValueExpression> <Operator>Equal</Operator> <ValueExpression> <Value Type="String">true</Value> </ValueExpression> </SimpleExpression> </Expression> </DataSource> </Discovery> </Discoveries> <Tasks> <Task ID="Example.SCOMMigration.RemoveOldMGTask" Accessibility="Internal" Enabled="true" Target="Example.SCOMMigration.OldMG" Timeout="300" Remotable="true"> <Category>Maintenance</Category> <WriteAction ID="Script" TypeID="Windows!Microsoft.Windows.ScriptWriteAction"> <ScriptName>RemoveOldMG.vbs</ScriptName> <Arguments /> <ScriptBody><![CDATA[On error resume next Dim objMSConfig Set objMSConfig = CreateObject("AgentConfigManager.MgmtSvcCfg") 'See if Mgmt Group exists Set objMG = objMSConfig.GetManagementGroup ("OMMG") If Err <> 0 Then wscript.echo "OMMG management group does not exist on this agent" wscript.quit End If 'Remove AD int or manually configured management group 'Check if AD Integration is enabled objADint = objMSConfig.GetActiveDirectoryIntegrationEnabled() If objADint <> 1 then wscript.echo "AD Integration is not enabled on this agent" wscript.echo "Removing old manually configured management group" Call objMSConfig.RemoveManagementGroup ("OMMG") else wscript.echo "AD Integration is enabled and returned value: " & objADint 'Disable AD Integration wscript.echo "Disabling AD Integration" Call objMSConfig.DisableActiveDirectoryIntegration() End If 'Restart agent healthservice out of band wscript.echo "Attempting to restart Healthservice out of band" dim strServiceName, objWMIService, colListofServices, objService strServiceName = "HealthService" dim sFilePath Dim objFSO 'As FileSystemObject Dim objTextFile 'As Object Dim oShell Set oShell = CreateObject( "WScript.Shell" ) temppath=oShell.ExpandEnvironmentStrings("%TMP%") 'wscript.echo "Temp Path" & temppath sText="net stop Healthservice && net start Healthservice" sFilePath=temppath & "\sshs.bat" 'wscript.echo "Writing to " & sFilePath Set objFSO = CreateObject("Scripting.FileSystemObject") Set objTextFile = objFSO.CreateTextFile(sFilePath, True) ' Write a line. objTextFile.Write (sText) objTextFile.Close oShell.run sFilePath]]></ScriptBody> <TimeoutSeconds>60</TimeoutSeconds> </WriteAction> </Task> </Tasks> <Monitors> <UnitMonitor ID="Example.SCOMMigration.OldMgExistsMonitor" Accessibility="Internal" Enabled="true" Target="Example.SCOMMigration.OldMG" ParentMonitorID="Health!System.Health.ConfigurationState" Remotable="true" Priority="Normal" TypeID="Example.SCOMMigration.OldMGExists.MonitorType" ConfirmDelivery="true"> <Category>Custom</Category> <OperationalStates> <OperationalState ID="UIGeneratedOpStateId12568c009a744c66a11a3d10f605a46a" MonitorTypeStateID="RegKeyExists" HealthState="Warning" /> <OperationalState ID="UIGeneratedOpStateIdfb9c9eca86164bdf99d155617a574b9e" MonitorTypeStateID="RegKeyMissing" HealthState="Success" /> </OperationalStates> <Configuration /> </UnitMonitor> </Monitors> </Monitoring> <Presentation> <Views> <View ID="Example.SCOMMigration.NewElement" Accessibility="Internal" Enabled="true" Target="Example.SCOMMigration.OldMG" TypeID="SC!Microsoft.SystemCenter.StateViewType" Visible="true"> <Category>Custom</Category> <Criteria /> </View> </Views> <Folders> <Folder ID="Example.SCOMMigration.FolderRoot" Accessibility="Internal" ParentFolder="SC!Microsoft.SystemCenter.Monitoring.ViewFolder.Root" /> </Folders> <FolderItems> <FolderItem ElementID="Example.SCOMMigration.NewElement" Folder="Example.SCOMMigration.FolderRoot" /> </FolderItems> </Presentation> <LanguagePacks> <LanguagePack ID="ENU" IsDefault="true"> <DisplayStrings> <DisplayString ElementID="Example.SCOMMigration"> <Name>Example SCOM Migration MP</Name> <Description /> </DisplayString> <DisplayString ElementID="Example.SCOMMigration.FolderRoot"> <Name>Example SCOM Migration</Name> <Description /> </DisplayString> <DisplayString ElementID="Example.SCOMMigration.NewElement"> <Name>Example SCOM Migration</Name> <Description /> </DisplayString> <DisplayString ElementID="Example.SCOMMigration.OldMG"> <Name>Old Management Group Class</Name> </DisplayString> <DisplayString ElementID="Example.SCOMMigration.OldMGDiscovery"> <Name>Old Management Group Class Discovery</Name> <Description /> </DisplayString> <DisplayString ElementID="Example.SCOMMigration.OldMGExists.MonitorType"> <Name>Old MG Exists MonitorType</Name> <Description /> </DisplayString> <DisplayString ElementID="Example.SCOMMigration.OldMgExistsMonitor"> <Name>Old Management Group Exists Monitor</Name> <Description /> </DisplayString> <DisplayString ElementID="Example.SCOMMigration.OldMgExistsMonitor" SubElementID="UIGeneratedOpStateId12568c009a744c66a11a3d10f605a46a"> <Name>RegKeyExists</Name> </DisplayString> <DisplayString ElementID="Example.SCOMMigration.OldMgExistsMonitor" SubElementID="UIGeneratedOpStateIdfb9c9eca86164bdf99d155617a574b9e"> <Name>RegKeyMissing</Name> </DisplayString> <DisplayString ElementID="Example.SCOMMigration.RemoveOldMGTask"> <Name>Remove Old ManagementGroup</Name> <Description /> </DisplayString> </DisplayStrings> </LanguagePack> </LanguagePacks> </ManagementPack>
My script is pretty simple – borrowing from a few examples above:
On error resume next Dim objMSConfig Set objMSConfig = CreateObject("AgentConfigManager.MgmtSvcCfg") 'See if Mgmt Group exists Set objMG = objMSConfig.GetManagementGroup ("OMMG") If Err <> 0 Then wscript.echo "OMMG management group does not exist on this agent" wscript.quit End If 'Remove AD int or manually configured management group 'Check if AD Integration is enabled objADint = objMSConfig.GetActiveDirectoryIntegrationEnabled() If objADint <> 1 then wscript.echo "AD Integration is not enabled on this agent" wscript.echo "Removing old manually configured management group" Call objMSConfig.RemoveManagementGroup ("OMMG") else wscript.echo "AD Integration is enabled and returned value: " & objADint 'Disable AD Integration wscript.echo "Disabling AD Integration" Call objMSConfig.DisableActiveDirectoryIntegration() End If 'Restart agent healthservice out of band wscript.echo "Attempting to restart Healthservice out of band" dim strServiceName, objWMIService, colListofServices, objService strServiceName = "HealthService" dim sFilePath Dim objFSO 'As FileSystemObject Dim objTextFile 'As Object Dim oShell Set oShell = CreateObject( "WScript.Shell" ) temppath=oShell.ExpandEnvironmentStrings("%TMP%") 'wscript.echo "Temp Path" & temppath sText="net stop Healthservice && net start Healthservice" sFilePath=temppath & "\sshs.bat" 'wscript.echo "Writing to " & sFilePath Set objFSO = CreateObject("Scripting.FileSystemObject") Set objTextFile = objFSO.CreateTextFile(sFilePath, True) ' Write a line. objTextFile.Write (sText) objTextFile.Close oShell.run sFilePath
Here is the view:
Health explorer for the monitor:
You can multi-select many agents and run the task:
Note – you MUST run the task as a user account that has local administrator rights on each agent. If you run the task as the default agent action account (local system) the service will stop but not restart. It is quite complicated to make a SCOM task that can reliably restart the SCOM service:
The output:
Pingback:Configure SCOM agent from PowerShell - Kevin Justin's Blog