Authoring .NET Modules for MPs

Pushing the Envelope; .NET Code in
SCOM Management Packs
Nathan Foreman
@Nate_Foreman
[email protected]
Jonathan Almquist
@jtalmquist
[email protected]
Nathan Foreman
@Nate_Foreman
Solutions
Engineer
#MMSMOA
10+
years in IT
Practice2Perfect
.com
Jonathan Almquist
@jtalmquist
Consultant,
blogger,
author, speaker
#MMSMOA
16 years
experience in IT,
past 10 years
focused on
Operations
Manager
TechNet Forum
Blogging since
2007
Overview and Agenda
Theory
• Why .NET?
• What’s .Net Modules
• Pros (& Cons)
• Functionality
• Microsoft Examples
• Elastic Search DW
• Development Concepts
•
•
•
•
•
Threading
Batching
Persistence
Acknowledgments/Notifications
Module Lifecycle
Implementation
• Making the Library (.dll)
• Create VS Project
• Signing the Builds
• References
• Class Construction
• Required Methods
• SyncLock
• Data & Control Flow
• Get the Module in SCOM
• Create Library MP
• Add Deployable Assembly
• Create & Use Module
Why .NET?
It’s not quicker or easier,
so what can we gain by
going this route?
What are .NET modules?
One of three Module Implementation [3,4]
• Native
• Managed
• Composite
They’ve been around for a while
• SCOM 2007 [4]
• “Creation or modification of native modules and managed modules is
not supported...”
• SCOM 2012 [5]
• Only create them, when provided modules “are insufficient for your
needs”
Why .NET? – Pros and Cons
Advantages
• Persisted State
• Compiled .NET code can
work faster [1]
• Harder to Tamper/Reverse
Engineer
• Full Featured IDE
• Leverage .NET Coding
Professionals
Disadvantages
• More Complicated than
Scripted Alternatives
• Additional Knowledge
required to write Code
• Requires additional Steps
for Distribution
• Updates to Code take
longer to deploy than
scripts.
Functionality & Examples
Microsoft Examples
• PowershellProbeBase
• PowershellProbe
• PowershellDiscoveryProbeBase
• PowershellDiscoveryProbe
• SystemCenter.GroupPopulator
• SystemCenter.EventWriter
• .DiscoveryDataWriter
• .PerformanceDataWriter
Elastic Search DW
• High Speed Logging
• 4,000 items Per Second
• Perf Collection Every 2
Seconds
• Reduce Database Size
• Smaller OpsDB
• Extended DW Retention
• Fast Searching and
Reporting
Demo
.NET Elastic Search DW
(Frontend)
Development Concepts
To get the most from your .NET modules
there are a few things to keep in mind.
Design and Development notes from Microsoft:
https://msdn.microsoft.com/en-us/library/hh769912.aspx
Development Concepts
Threading
• Not a Unique concern to .NET
• Health Service is a Shared Environment
• IO Bound: Use Async Methods
• CPU Bound: Perform work Synchronously
Batching [6]
• Allows Multiple Items per Execution
• Not relevant for composite module types
• Consolidation Modules with multiple Items
Development Concepts
Persistence
• Save State between Executions
• Module Host handles data
• Cleared on Module Change
Acknowledgments
• Transactional Data Flow not Supported [5]
• Responsible until Acknowledgment
Completion Notifications
• Notifies Health Service work is Complete
• Must Notify Completion before next Request
Development Concepts
Startup and Shutdown
• Constructor
• Start
• Called After Constructor Completes
• Must be Thread Safe with NotifyStop
• NotifyStop
• Notifies of a graceful shutdown
• Shutdown
• About to be Unloaded, time to save State
Engine may Unload without Notice
• Module must not corrupt threads
Making the Library
Implementation is where
the fun really is.
New Visual Studio Project
Create a Class Library Project
• Sign the Build
• Set the Namespace
• Strong Named Assemblies Required
https://msdn.microsoft.com/en-us/library/ms227566(v=vs.80).aspx
Handle Required References
• Are they on the Target?
• Embed Resources you may Need
http://www.codeproject.com/Articles/528178/Load-DLL-FromEmbedded-Resource
Class Definition
Attributes
• MonitoringModule(ModuleType.WriteAction)
• ModuleOutput (True/False)
Inherits ModuleBase Of DataItemBase
Global Variables
• SyncLock Object
• Shutdown in Progress Boolean
Class Construction: Code
VB.NET
<MonitoringModule(ModuleType.WriteAction)> _
[MonitoringModule(ModuleType.WriteAction)]
<ModuleOutput(False)>
_
Public
[ModuleOutput(false)]
NotInheritable Class WriteToES
public sealed
'Inherit
the ModuleBase
class WriteToES
we will be working off of
Inherits
: ModuleBase<DataItemBase>
ModuleBase(Of DataItemBase)
{
'Shared
//Shared
objects
objects,
are accessible
accessible
from
from
allall
instances
instances
Shared
static
Logger
P2PLogging
As P2PLogging
Logger;
Shared
static
ShutdownInProgress
bool ShutdownInProgress;
As Boolean
'Global
//Global
object,
object,
controls
controls
activity
activity
via SyncLocks
via SyncLocks
Private
private
shutdownLock
object shutdownLock;
As Object
'Making
//Making
Global,
Global,
reducing
reducing
instantiation
instantiation
cost cost
Private
private
ESConnector
ElasticSearchConnector
As ElasticSearchConnector
ESConnector;
Private
private
DataItemCollection
DataItemProcessor
As DataItemProcessor
DataItemCollection;
C#
Required Methods - New
Signature
• moduleHost As ModuleHost(Of DataItemBase)
• configuration As XmlReader
• previousState As Byte()
Setup your Module
• Logging
• Libraries
• Configuration Parsing
New Method: Code
VB.NET
C#
public Sub
WriteToES(ModuleHost<DataItemBase>
XmlReader
configuration,
byte[] previousState
previousState)As Byte())
Public
New(moduleHost As ModuleHost(OfmoduleHost,
DataItemBase),
configuration
As XmlReader,
: base(moduleHost)
{
'Call the Base Constructor
//Verify
we Have everything we need
MyBase.New(moduleHost)
if (configuration == null)
{ 'Verify we Have everything we need
throw
(new Exception("configuration
isNew
nothing"));
If
configuration
Is Nothing Then Throw
Exception("configuration is nothing")
}
'Add the Additional Libraries to our instantiation
//Add the Additional Libraries to our instantiation
Dim LibraryLoader As New LibraryLoader(Assembly.GetExecutingAssembly(), False)
LibraryLoader LibraryLoader = new LibraryLoader(Assembly.GetExecutingAssembly(), false);
LibraryLoader.LoadLibrariesFromResources()
LibraryLoader.LoadLibrariesFromResources();
'Extract
from
Config
what
need
initiate
connections.
//Extract
from
Config
what
we we
need
andand
initiate
thethe
connections.
Dim InstanceConfig
As ParsedConfigData
ParsedConfigData
InstanceConfig
= new ParsedConfigData();
InstanceConfig
= ExtractConfigData(configuration)
InstanceConfig
= ExtractConfigData(configuration);
'Create
Classes
will
throughout
life
this
module
//Create
thethe
Classes
we we
will
useuse
throughout
thethe
life
of of
this
module
Logger
= New
P2PLogging
Logger
= new
P2PLogging();
DataItemCollection
DataItemCollection
= new
= New
DataItemProcessor(Logger);
DataItemProcessor(Logger)
shutdownLock
= new
object();
shutdownLock
= New
Object()
Required Methods - Start
Empty Signature
Check for Shutdown
Lock
• ModuleHost.RequestNextDataItem()
Start Method: Code
VB.NET
public
Publicoverride
Overrides
void
SubStart()
Start()
{
SyncLock
lock(shutdownLock)
shutdownLock
{
'We don't need to continue if Shutdowns are starting.
//WeIfdon't
ShutdownInProgress
need to continue
Then
if Shutdowns are starting.
if (ShutdownInProgress)
Return
{
End If
return ;
}
'Request the first data batch.
'The ME keyword unambiguously refers to this instance
//Request
Me.ModuleHost.RequestNextDataItem()
the first data batch.
//The ME keyword unambiguously refers to this instance
End
this.ModuleHost.RequestNextDataItem();
SyncLock
}
}
End Sub
C#
Required Methods - OnNewDataItems
Denote Input Stream Number
• [InputStream(0)]
Signature
• dataItems As DataItemBase()
• logicallyGrouped As Boolean
• acknowledgedCallback As DataItemAcknowledgementCallback
• acknowledgedState As Object
• completionCallback As DataItemProcessingCompleteCallback
• completionState As Object
Do work with the DataItems()
Lock
• ModuleHost.RequestNextDataItem()
OnNewDataItems Method: Code
VB.NET
C#
[InputStream(0)]
<InputStream(0)> _
public
OnNewDataItems(DataItemBase[]
dataItems, bool logicallyGrouped,
Public void
Sub OnNewDataItems(dataItems
As DataItemBase(),
logicallyGrouped DataItemAcknowledgementCallback
As Boolean, acknowledgedCallback As
acknowledgedCallback,
object acknowledgedState,
DataItemProcessingCompleteCallback
completionCallback,
object
DataItemAcknowledgementCallback,
acknowledgedState
As Object, completionCallback
As
completionState)
DataItemProcessingCompleteCallback, completionState As Object)
{
have been
been shutdown
shutdown stop
stop processing.
'//IfIfwewehave
processing.
if (ShutdownInProgress)
If ShutdownInProgress Then
{
Logger.WriteInformation("Shutdown
in Progress")
Logger.WriteInformation("Shutdown in Progress");
Return
return ;
End
If
}
'
you will
will do
perform
you work
the removed
DataItems()
// This
This is
is where
where you
your work,
code with
has been
for Space
SyncLock
shutdownLock
lock(shutdownLock)
{
Me.ModuleHost.RequestNextDataItem()
this.ModuleHost.RequestNextDataItem();
End SyncLock
}
}
End Sub
Required Methods - Shutdown
Empty Signature
Lock
• Mark Global Shutdown in Progress
• Cleanup as Needed
• Finalize()
Shutdown Method: Code
VB.NET
public Overrides
Public
override void
Sub Shutdown()
{
'Lock
//Locktotoprevent
preventother
otheroperations
operationsduring
duringShutdown
Shutdown
SyncLock
lock(shutdownLock)
shutdownLock
{
ShutdownInProgress = True
Me.Finalize()
ShutdownInProgress = true;
End SyncLock
//Cleanup Here
}
}
End Sub
C#
Getting The Module in SCOM
It’s time to get back into familiar territory
Creating a Library Management Pack
DeployableAssembly
• Fully Qualified Assembly Name
<Resources>
<DeployableAssembly
ID="P2P.ManagedScomModules"
Accessibility="Public"
FileName="ManagedSCOMModules.dll"
HasNullStream="false"
QualifiedName="ManagedSCOMModules, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d49ecc768c087c65"/>
</Resources>
DLL in Management Pack Project
• Set Build Action = Embedded Resource
Create the Write Action Module
<ModuleTypes>
<WriteActionModuleType ID="P2P.Library.WriteToElasticSearch" Accessibility="Public" Batching="true">
<Configuration>
<xsd:element name="ElasticSearchNode" type="xsd:string" />
<xsd:element name="WinEventIndex" type="xsd:string" />
<xsd:element name="AllOtherIndex" type="xsd:string" />
<xsd:element name="TryBulkInsert" type="xsd:boolean" />
</Configuration>
<ModuleImplementation Isolation="Any">
<Managed>
<Assembly>P2P.ManagedScomModules</Assembly>
<Type>ManagedSCOMModules.WriteToES</Type>
</Managed>
</ModuleImplementation>
<InputType>System!System.BaseData</InputType>
</WriteActionModuleType>
</ModuleTypes>
Create a Pack with Actions
<Rule ID="P2P.Custom.LogTester.ProcessProc" Target="Windows!Microsoft.Windows.Server.Computer"
Enabled="true" ConfirmDelivery="false" Remotable="true" Priority="Normal" DiscardLevel="100">
<Category>PerformanceCollection</Category>
<DataSources>
<DataSource ID="DS" TypeID="Perf!System.Performance.DataProvider">
<ComputerName>.</ComputerName>
<CounterName>% Processor Time</CounterName>
<ObjectName>Process</ObjectName>
<AllInstances>true</AllInstances>
<Frequency>2</Frequency>
</DataSource>
</DataSources>
<WriteActions>
<WriteAction ID="WriteToES" TypeID="PCMML!P2P.Library.WriteToElasticSearch"
Target="SC!Microsoft.SystemCenter.CollectionManagementServer">
<ElasticSearchNode>http://p2p-elastic-01.cloudapp.net:13580</ElasticSearchNode>
<WinEventIndex>SCOMWinEvents</WinEventIndex>
<AllOtherIndex>SCOMDataItems</AllOtherIndex>
<TryBulkInsert>true</TryBulkInsert>
</WriteAction>
</WriteActions>
</Rule>
Demo
Putting Everything Together.
References
1. http://leporelo.eu/blog.aspx?id=powershell-performancecomparison-compiled-code-cmdlet-or-net-call
2. https://msdn.microsoft.com/enus/library/7k989cfy(v=vs.90).aspx
3. http://social.technet.microsoft.com/wiki/contents/articles/15
219.operations-manager-management-pack-authoringmodule-implementations.aspx
4. https://technet.microsoft.com/en-us/library/ff381347.aspx
5. https://msdn.microsoft.com/en-us/library/hh769912.aspx
6. https://nocentdocent.wordpress.com/2014/07/05/onemodule-to-rule-them-all-a-custom-scom-managedmodule-sysctr/
Discuss…
Ask your questions-real world answers!
Plenty of time to engage, share knowledge.
Evaluations: Please provide session feedback by clicking the EVAL button in the scheduler app (also
download slides). One lucky winner will receive a free ticket to the next MMS!
SPONSORS
Session Title:
Pushing the Envelope; .NET Code in SCOM Management Packs