There have been a few requests recently for more granular notification subscriptions. While this is fully supported, our UI is limited in what it exposes for users to tweak. Here is a look at the SDK and how to use it to create a subscription (and related objects).
First of all, to use subscriptions, you need to setup some auxiliary objects. In my example below, the first thing I create is an endpoint. We support Sip, Sms and Smtp. The endpoint is stored as a ModuleType in the database, although this is abstracted away by the API. The fact that it's a module type, however, means that the name has to follow the naming restrictions for management pack elements. After the endpoint, I create an action (also a ModuleType). The action combines an endpoint with configuration that allows the format of the endpoint to be specified. In the Smtp case, this allows you to specify email properties. Finally, I create a recipient that the subscription will be targeted to.
The actual subscription involves combining all the aforementioned components and specifying the criteria by which to filter notifications. In SCOM 2007, notifications are based on alerts. You configure which alerts you want to trigger notifications by using the AlertNotChangedSubscriptionConfiguration and the AlertChangedSubscriptionConfiguration classes. These are also used for connector framework subscriptions to mark alerts for forwarding. These two classes represent criteria by which to match alerts. The first matches alert that have not changed that match the criteria while the latter matches alerts that have changed that match the criteria. Both work off a polling interval. If you look at the classes in the SDK, you will notice that you can specify groups and classes to filter by, but what I really wanted to outline here was the criteria property as this is what is really not exposed fully by the UI. The criteria has to match the schema as defined in the Microsoft.SystemCenter.Library called AlertCriteriaType. Note, you don't need the Expression tag, that is filled in for you. In terms of which columns you can query for in the criteria, it is anything that is defined on the Alert table in the db.
EDIT: Stefan Koell has put together a great powershell example to accomplish the same task.
Here's the code:
(Note - If the criteria is not all on one line, it doesn't work correctly, that's why the formatting is a bit weird below. If you select the code, the full criteria should select)
partial class Program
static void InsertSubscription()
// Connect to the sdk service on the local machine
ManagementGroup localManagementGroup = new ManagementGroup("localhost);
// Setup an Smtp Endpoint
SmtpServer smtpServer = new SmtpServer("localhost");
smtpServer.PortNumber = 42;
// The guid is here for a unique name so this can be rerun
SmtpNotificationEndpoint smtpEndpoint =
"SmtpEndpoint_" + Guid.NewGuid().ToString().Replace('-', '_'),
smtpEndpoint.DisplayName = "My Smtp Endpoint";
smtpEndpoint.Description = "This is my Smtp Endpoint";
smtpEndpoint.MaxPrimaryRecipientsPerMail = 10;
smtpEndpoint.PrimaryServerSwitchBackIntervalSeconds = 15;
// This commits the endpoint into the system
// Setup the Smtp Action (this includes email format)
SmtpNotificationAction smtpNotificationAction =
"SmtpAction" + Guid.NewGuid().ToString().Replace('-', '_'));
smtpNotificationAction.Body = "Body";
smtpNotificationAction.Description = "Description";
smtpNotificationAction.DisplayName = "DisplayName";
smtpNotificationAction.Endpoint = smtpEndpoint;
smtpNotificationAction.From = "Test@Test.com";
new SmtpNotificationActionHeader("Name", "Value"));
smtpNotificationAction.IsBodyHtml = false;
smtpNotificationAction.ReplyTo = "firstname.lastname@example.org";
smtpNotificationAction.Subject = "my subject";
// This commits the action into the system
// Setup a recipient
NotificationRecipientScheduleEntry scheduleEntry =
new NotificationRecipientScheduleEntryTime(8, 0);
new NotificationRecipientScheduleEntryTime(17, 0);
NotificationRecipientDevice recipientDevice =
new NotificationRecipientDevice("smtp", "email@example.com");
recipientDevice.Name = "TestDevice";
NotificationRecipient recipient =
new NotificationRecipient("RecipientName" + DateTime.Now.ToString());
// Commits the recipient
// Alert configuration
AlertNotChangedSubscriptionConfiguration config =
config.Criteria = "<SimpleExpression><ValueExpression><Property>ResolutionState</Property></ValueExpression><Operator>Equal</Operator><ValueExpression><Value>255</Value></ValueExpression></SimpleExpression>";
config.ExpirationStartTime = DateTime.Now;
config.PollingIntervalMinutes = 1;
AlertNotificationSubscription alertChangeSubscription =
"MyNewAlertChangeSubscription" + Guid.NewGuid().ToString().Replace('-', '_'),
alertChangeSubscription.DisplayName = "My Subscription";
alertChangeSubscription.Description = "My Subscription Description";
// Commits the subscription
Well, it has been quite a holiday! My wife delivered our son, Jamison Jakub, on December 26th at 8:14 AM. Mom and baby are doing great. I've posted some photos on our families personal site: www.oleksyfamily.com. I am more or less back at work for now and will be taking my paternity leave later, most likely after we ship SCOM 2007.
I wanted to talk a little about management pack authoring and editing in the SDK. This is the largest part of the SDK that I did not write, so I am not an expert at the internal workings of a lot of it, but I do know how it works.
First, there is a rather large object hierarchy when it comes to management pack related objects. At the most derived level, you will almost always find a Monitoring* object derived from a ManagementPack* object (e.g. MonitoringRule and ManagementPackRule). Monitoring* objects are returned by the online, connected SDK from the database. These objects are not "newable" and contain slightly more context, and sometimes more functionality, then their respective base class. (For instance they always have a pointer to ManagementGroup, which ManagementPack* object do not). Whenever you want to create a new management pack object, you have to use the ManagementPack* version of it to create it.
The context of a management pack object is always a management pack. When you create an object, you need to specify which management pack it goes into. This is the management pack that the ultimate commit call (AcceptChanges()) will need to be made.
If you want to change an existing object, simply change whatever you want about it (i.e. any settable properties) and then set its Status property to PendingUpdate. Once you do this, internally it gets placed into a pending changes collection for that management pack. But which instance you might ask? If you are working in connected SDK and you retrieve a management pack object from the database that object belongs to a particular management pack. Internally, this management pack is cached (unless you are running on CacheMode.None in which you should not be doing management pack authoring) and we always maintain the same instance of that management pack. No matter how many times you retrieve that object, that management pack instance will be the same. In fact no matter how you retrieve that management pack (with the ONE caveat that if you do criteria based searching for a management pack, the instance will actually be different as it doesn't use the cache to perform the query) it will be the same instance.
This poses an interesting problem in that if multiple users in the same application try to update the same management pack, they will be writing into the same management pack at the same time. To alleviate this problem, the ManagementPack class exposes a LockObject property that will lock the management pack for editing. This lock should be taken prior to updating the management pack and released after committing the changes.
In order to commit changes, simply retrieve the management pack you are changing (either by calling GetManagementPack() on the object(s) you are changing, or some other independent SDK method that is not criteria based) and call AcceptChanges(). Once this method returns, the changes are committed.
I am sure users will have questions in this area, but it is such a large topic to cover, I just wanted to put together a small quick start guide to get everyone started. As always, please ask any questions you might have or if you want an expanded post on anything in particular regarding this area.