MPAuthor – A more advanced PowerShell Performance Collection Rule


 

In a previous post – I demonstrated using MPAuthor to create a VERY simple Powershell script based perf collection rule:  http://blogs.technet.com/b/kevinholman/archive/2015/06/19/mpauthor-using-a-powershell-script-to-collect-performance-data-in-a-scom-rule-101.aspx

Now I am going to demonstrate a more advanced script with multiple propertybags, script parameters, and adding references for custom target classes.

I’ll be using the base script from:  http://blogs.technet.com/b/kevinholman/archive/2015/06/20/using-a-net-assembly-in-powershell-when-a-cmdlet-doesn-t-exist-a-microsoft-service-bus-example.aspx

First we need to tweak the script for use in SCOM.  See my “101” post linked above on how to do this.  I basically added in the MOMScript API, added some logging, and then created the PropertyBags I want to supply to the SCOM rule:

# Service Bus Queue Size Script for SCOM # Author: Kevin Holman # Version 1.0 param($NamespaceName, $QueueName, $HostName) #$NamespaceName = "ServiceBusDefaultNamespace" #$QueueName = "testqueue3" #$HostName = "sb01.opsmgr.net" #Provide a path to the DLL you wish to load that provides and SDK API $assemblyLocation = "C:\Program Files\Service Bus\1.1\Microsoft.ServiceBus.dll" #Get who the script is running as $whoami = whoami #Load the MOMScript API, PropertyBag, and log a starting script event $api = New-Object -comObject 'MOM.ScriptAPI' $bag = $api.CreatePropertyBag() $api.LogScriptEvent("SBUSQueueSize.ps1",100,4,"Starting queue size script RunAs $whoami for $namespaceName and $QueueName") #Load the .NET assembly [Void][System.Reflection.Assembly]::LoadWithPartialName("System") [Void][System.Reflection.Assembly]::LoadFile($assemblyLocation) #Create a connection string which is required for the service bus API for a given namespace in Service Bus $conn = "Endpoint=sb://" + $HostName + "/" +$NamespaceName + ";StsEndpoint=https://" + $HostName +":9355/" + $NamespaceName +";RuntimePort=9354;ManagementPort=9355" #Load the NamespaceManager Class from the connectionstring $NamespaceManager = [Microsoft.ServiceBus.NamespaceManager]::CreateFromConnectionString($conn) #Get the array of all queues in the namespace $Queues = $NamespaceManager.GetQueues() #Get the current Queue Size in bytes from the Queue object foreach ($queue in $Queues) { IF ($queue.Path -eq $QueueName) { $QueueSize = $queue.SizeInBytes #Log an event that the script is complete $api.LogScriptEvent("SBUSQueueSize.ps1",101,4,"Ending queue size script RunAs $whoami for $NamespaceName and $QueueName with queue size $QueueSize bytes") #Add the data into the PropertyBag $bag.AddValue("NameSpace",$NamespaceName) $bag.AddValue("QueueName",$QueueName) $bag.AddValue("QueueSizeBytes",[UInt32]$QueueSize) } } #Output the PropertyBag data for SCOM consumption: $bag

Open MPAuthor and create a new MP:

image

Save it to a path.  Click Next on the reference page.  Choose “Empty Management Pack”

One of the first things we will do is add a new reference.  In MPAuthor – Tools, “Set Reference Management Pack Folder”, you provide a path to all your reference MP’s.  You can dump all your MP’s you want to use into this path, or, you can add multiple paths separating them with a semicolon:

image

 

To add a reference – right click the MP name in the upper left corner and choose add reference:

image

 

Find your MP in the list:

image

 

You can see the reference was added:

image

 

Now that we loaded the reference – we can create rules that target classes in that referenced MP.  This is a good time to Save the MP to a file.

Create a new script performance rule.  Provide a script name and paste in the modified script:

image

 

Next – our script requires three params, so we must provide them here.  Now – ideally, I want to pass these params as variables that represent class properties from my targeted class.  MPAuthor doesn’t have a class browser so we will have to pass this manually.

Additionally, because in this case I am referencing an MPB file, MPAuthor has some issues resolving class properties from these file types, so I will be putting in some static “dummy” script parameters and then will fix these up in XML.

After putting in your three params, set the timeout for the script as appropriate.

image

 

On the performance Mapper page, we can use static text, or output from PropertyBags.  I am outputting three propertybags in the script, for use here:

From the script:

#Add the data into the PropertyBag
$bag.AddValue("NameSpace",$NamespaceName)
$bag.AddValue("QueueName",$QueueName)
$bag.AddValue("QueueSizeBytes",[UInt32]$QueueSize)

Matches up to:

image

 

Next we pick a target class.  I want this script to run for each queue, because I will use the Queue Name and Namespace target class properties as script params to identify which namespace and queue to collect performance data for, and this way each object will have its own instance of performance data.

image

 

Then give the rule a proper ID, name, and description:

image

 

Check the box to save data to the DW:

image

 

Provide a schedule that makes sense for performance data.  I am only using 60 second for testing.  In product we would never want a PowerShell script running that often, especially this one since there are multiple instances of Queue and it does not support CookDown.

image

 

Finish and save the new MP. At this point for testing you could import it…. however it is not finished because we used hard coded script parameters, so all the queues will show the same value.

I decide this would be a good time to import and test…. just to shake out any MAJOR bugs, like failure to import, workflow failure, etc…

It works!  I am getting events in my OpsMgr event log:

Log Name:      Operations Manager
Source:        Health Service Script
Date:          6/20/2015 9:56:32 PM
Event ID:      101
Task Category: None
Level:         Information
Keywords:      Classic
User:          N/A
Computer:      SB01.opsmgr.net
Description: SBUSQueueSize.ps1 : Ending queue size script RunAs nt authority\system for ServiceBusDefaultNamespace and testqueue3 with queue size 5040 bytes

Looking at the event, I see that this script is running as the Default Agent Action account.  That is Local System.  Well, local system might not have any rights to Service Bus.  It appears in my case Local System is working fine.  But what if it didn’t, and we wanted to use our RunAs account we already set up for Service Bus?

In this case, I need to ad a RunAs Profile reference to my Rule in the MP – to make this workflow run as my Service Bus RunAs account.  So I will do that now.

First – I need to reference the MP where my SBUS RunAs profile exists.  This is in the Microsoft.ServiceBus.v1.1.mp.    For some reason MPAuthor wont let me add this as a reference, so I am just going to do it manually.

In the Manifest section of the XML, I add the reference:

<Reference Alias="ServiceBus11">
  <ID>Microsoft.ServiceBus.v1.1</ID>
  <Version>1.0.0.26</Version>
  <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
</Reference>

Next – I need my module to load the RunAs Profile that is already in use for the Service Bus Management Pack.  Alternatively – I could create a new RunAs profile in this pack, but that would be extra work.  To get an example of how to reference this RunAs account, I crack open the XML of the Service Bus 1.1 MP.

So I find an example of this in the Service Bus MP – where a Discovery calls a datasource type, it also references the RunAs profile.  So I will place my reference on the Rule, where the Rule calls the Datasource.  The only thing I need to change is to add in the reference, since the RunAs profile definition exists in a different MP and not this one.  This is the code I need to add:

RunAs="ServiceBus11!Microsoft.ServiceBus.v1.1.SBDiscoveryMonitoringProfile

Below you will see the statement added to the Rule’s datasource statement:

<Rule ID="Microsoft.ServiceBus.Addendum.QueueSize.Rule" Enabled="true" Target="Alias6!Microsoft.IT.SCOM.SBWS.Queue" ConfirmDelivery="false" Remotable="true" Priority="Normal" DiscardLevel="100"> <Category>PerformanceCollection</Category> <DataSources> <DataSource ID="DataSource" TypeID="Microsoft.ServiceBus.Addendum.QueueSize.Rule.DataSourceModuleType" RunAs="ServiceBus11!Microsoft.ServiceBus.v1.1.SBDiscoveryMonitoringProfile"> <TimeoutSeconds>60</TimeoutSeconds> <IntervalSeconds>60</IntervalSeconds> </DataSource> </DataSources>

I increment my version – save my XML, and reimport for testing.

Now – I am seeing what I expected – the script is running under my Service Bus RunAs Account:

Log Name:      Operations Manager
Source:        Health Service Script
Date:          6/20/2015 10:06:25 PM
Event ID:      101
Task Category: None
Level:         Information
Keywords:      Classic
User:          N/A
Computer:      SB01.opsmgr.net
Description:
SBUSQueueSize.ps1 : Ending queue size script RunAs opsmgr\sbscom for ServiceBusDefaultNamespace and testqueue3 with queue size 5040 bytes

Last step – we need to change the script parameters from hard coded values – to variables that resolve to class properties.

In the ProbeAction Module – just past the script – there is a “<Parameters>" section:

<Parameters>
  <Parameter>
    <Name>NamespaceName</Name>
    <Value>ServiceBusDefaultNamespace</Value>
  </Parameter>
  <Parameter>
    <Name>QueueName</Name>
    <Value>testqueue3</Value>
  </Parameter>
  <Parameter>
    <Name>HostName</Name>
    <Value>sb01.opsmgr.net</Value>
  </Parameter>
</Parameters>

We want to change these to the resolvable XPATH variables from properties of the class which we have already discovered:

<Parameters>
  <Parameter>
    <Name>NamespaceName</Name>
    <Value>$Target/Host/Property[Type="Alias6!Microsoft.IT.SCOM.SBWS.Namespace"]/NamespaceName$</Value>
  </Parameter>
  <Parameter>
    <Name>QueueName</Name>
    <Value>$Target/Property[Type="Alias6!Microsoft.IT.SCOM.SBWS.Queue"]/QueueName$</Value>
  </Parameter>
  <Parameter>
    <Name>HostName</Name>
    <Value>$Target/Host/Property[Type="Alias6!Microsoft.IT.SCOM.SBWS.Namespace"]/HostName$</Value>
  </Parameter>
</Parameters>

Save and import – and it works great!  Now I am collecting data for each queue independently.  The only negative about this solution as it is, is that since I am passing different data to the datasource for each targeted instance of “Queue”, the script does not cook down.  We will run the PowerShell script one time for each instance of Queue.  If you have a small number of queues this is no bother.  If you have a very large number of queue this can potentially cause a performance issue.

I add a folder and a performance view to the MP:

image

 

Now that we have a foundation, I can repeat this process for a monitor, or use the existing datasource and probe action created for the rule, and add a monitortype and monitor if needed.  As always, I’ll attach my sample XML below.

Microsoft.ServiceBus.Addendum.xml.zip


Comments (0)

Skip to main content