Archive

Posts Tagged ‘GetManagementPack’

ssPortal: Revisiting the Custom Monitoring Report Web Service

May 16, 2011 2 comments

Now that the custom CPU, Disk, and Memory thresholds have been implemented, we need to revisit the Custom Monitoring Report, specifically the Web Service methods that interrogate SCOM.

Remember that all custom settings are held in a customer-specific management pack. However, the RSPerf groups that are used to implement the threshold overrides reside in a separate management pack. I suppose, we could have created all of the RSPerf groups in each customer MP, but that would have been a maintenance nightmare. Suppose we want to add or remove a threshold value? We would have to make the change in hundreds, perhaps thousands of management packs. No, thank you.

So, we put the RSPerf groups into their own MP. But that means the GetCustomMonitoring web service method needs to be updated. In addition to getting all the overrides in the customer’s MP, the method now needs to also check the RSPerf MP to see if any of the customer’s servers are members of any of the RSPerf groups.

First, modify the public method to call a private function(GetSSPortalThresholds) that will return the RSPerf data to be included in the report.

GetCustomMonitoring Web Service public method

public XmlDocument GetCustomMonitoring(string DC, int Account)
{
    WebServiceXML ReturnXML = new WebServiceXML();
    try
    {
        ConnectManagementGroup(DC);

        ManagementPackCriteria mpCriteria = new ManagementPackCriteria(“DisplayName like ‘%” + Account + “%'”);
        ReadOnlyCollection<ManagementPack> mpList = mg.GetManagementPacks(mpCriteria);
        if (mpList.Count > 0)
        {
            ManagementPack mp = mpList[0];
            GetOverrides(mg, mp);

            GetSSPortalThresholds(DC, Account);

            ovList.Sort();
        }
                
        BuildTable();
        ReturnXML.SetStatus(WebServiceXML.ServiceStatus.Succeeded);
        ReturnXML.AddData(tblRules.FirstChild.InnerXml);
        CreateCacheDependency(PortalSystem.SCOM, FunctionalArea.CustomReporting,HttpContext.Current.Request.Url.Query);
             
    }
    catch (Exception ex)
    {
        EventLogWriter.LogEvent(ex);
        ReturnXML.SetStatus(WebServiceXML.ServiceStatus.Failed, GenericErrorMsg);
        InvalidateCachePage(PortalSystem.SCOM, FunctionalArea.CustomReporting, HttpContext.Current.Request.Url.Query);
    }
    return ReturnXML.Root;
}//GetCustomMonitoring

This new function(and it’s sub function) use the SCOM extension methods developed earlier to determine group membership – specifically, the MemberOf() method, which returns a dictionary of all the groups(and their guid) that a particular object(server or disk drive) is a member of.

GetSSPortalThresholds private function

        private void GetSSPortalThresholds(string dc, int acct)
        {
            XmlDocument xd = sa.GetAgents(dc, acct, string.Empty); //Get the list of servers for the account
            XmlNode status = xd.SelectSingleNode(“/Response/Status”);
            XmlNodeList serverList = xd.SelectNodes(“/Response/ReturnData/Server”);

            foreach (XmlNode svr in serverList)
            {
                //get ssPortal thresholds for the server object
                PartialMonitoringObject pmoServer = mg.GetPartialMonitoringObject(new Guid(svr.Attributes["guid"].Value));
                GetObjectThresholds(pmoServer);

                //Get the ssPortal thresholds for the logical disk drives on this server
                string critString = “Path like ‘%” + svr.InnerText + “%’ AND FullName Like ‘%LogicalDisk%'”;
                MonitoringObjectGenericCriteria crit = new MonitoringObjectGenericCriteria(critString);
                ReadOnlyCollection<PartialMonitoringObject> driveList = mg.GetPartialMonitoringObjects(crit);

                foreach (PartialMonitoringObject pmoDrive in driveList)
                    GetObjectThresholds(pmoDrive);

            }//foreach
          }//GetssPortalThresholds
        
        private void GetObjectThresholds(PartialMonitoringObject pmo)
        {
            Dictionary<string, string> dctGroups = pmo.MemberOf(); //get the list of groups this object is a member of

            //use LINQ to get just the RSPerf groups
            var ssPortalThresholdList = from grp in dctGroups
                                        where grp.Value.Contains(“RSPerf”)
                                        select grp.Value;

            foreach (var th in ssPortalThresholdList)
            {
                string s = (string)th.Substring(7); //chopp off the “RSPerf.” since has no real meaning to an end user
                SCOMCustomOverride sco = new SCOMCustomOverride();
                sco.Name = “ssPortal Custom Threshold”;
                sco.Type = “RSPerf”;

                // split the RSPerf….. group name into pieces that can be plugged into the SCOMCustomOverride object
                string[] grpSplit = s.Split(‘.’); //split at the ‘.’
                string counter = grpSplit[0]; //counter is before the .
                string thresh = grpSplit[1]; // threshold is after the .

                string[] cntrSplit = counter.Split(‘_’); //further split the counter name at the underscores
                sco.Config = “<Config type=\”RSPerf\”>” + cntrSplit[0] + “</Config>”; //Counter Group is before the first _
                
                // actual counter name is everything after the first _
                // some counter names include _ to further qualify them, such as “PctUtilization_30m” meaning
                // % utilization averaged over a 30 min period. The counter.split() above would put the “30m”
                // into a 3rd string
                // code below puts this 3rd string, if present, into ( ) before sticking it into the SCO object
                sco.Override = cntrSplit.Length == 2 ? cntrSplit[1] : cntrSplit[1] + “(” + cntrSplit[2] + “)”;
                sco.Override += “=” + thresh;
                sco.Override = “<Override>” + sco.Override + “</Override>”;

                sco.Target = pmo.Path == null ? pmo.DisplayName : pmo.Path + “\\” + pmo.DisplayName;
                sco.Target = “” + sco.Target + “”;

                ovList.Add(sco);
            }
        }

ssPortal: Create/Update Custom SCOM Rules with the SDK (Part 1)

March 3, 2011 Leave a comment

The CreateEventRule web service method is very similar to the CreateServiceStateMonitor:

  • connect to the management group based on the DC parameter
  • gets the MP for the Account parameter
  • Creates a disabled Rule
  • Creates the Rule datasource from the passed in parameters
  • Creates the Alert settings, the alert text is set to the same text as the Rule name
  • write the Audit Trail record
  • return the GUID of the newly created Rule

The major difference from the CreateServiceStateMonitor is the way alerts are generated. The SCOM UnitMonitor class has built-in AlertSettings property, which makes it easy to create the alert. For some reason, though, the ManagementPackRule class does not have a similar property. So the alerting for a rule has to be built manually with XML strings.

As with the CreateServiceStateMonitor method there are related public methods to Update, Enable, Disable, and Get Custom Event Rules.

Create/Update Event Rule methods and associated helper functions

   #region Custom Event Rules

        [WebMethod]
        public XmlDocument CreateEventRule( string DC, int Account,
                                            string AlertText, string EventLogName,
                                            string EventIDExpression, string EventSourceExpression,
                                            string EventLevelExpression, string EventDescriptionExpression,
                                            string Ticket,
                                            string UserID)
        {
         
            WebServiceXML ReturnXML = new WebServiceXML();
            try
            {
                string AcctRuleName = string.Empty;
                string AcctAlertName = string.Empty;

                if (AlertText.StartsWith(Account.ToString())) //does the alert text begin with the acct# ??
                {
                    AcctAlertName = AlertText; //yes – do nothing
                }
                else
                {
                    AcctAlertName = Account.ToString() + ” – ” + AlertText; //else add acct# to rule name
                }

                string RuleID = Guid.NewGuid().ToString().Replace(“-“, string.Empty); //generate a guid and strip out the dashes
                string mpRuleName = “WebServiceRule” + RuleID; //generate an internal name

                //connect to the Management Group
                ConnectManagementGroup(DC);

                ManagementPack mp = mg.GetManagementPacks(“rs” + Account.ToString())[0];
                if (mp != null) //if mp is not found, return empty data
                {
                    ManagementPackRule rule = new ManagementPackRule(mp, mpRuleName);
                    rule = new ManagementPackRule(mp, mpRuleName);
                    rule.Target = WinComputerClass;
                    rule.Category = ManagementPackCategoryType.Custom;
                    rule.DisplayName = AcctAlertName; //display name and alert text are the same
                    rule.Description = DateTime.Now.ToShortDateString() + ” – #” + Ticket + ” Rule created by ” + UserID + ” via ssPortal”;
                    
                    rule.Enabled = ManagementPackMonitoringLevel.@false;

                    string xmlCfg = CreateConfigXML(EventLogName, EventIDExpression, EventSourceExpression, EventLevelExpression, EventDescriptionExpression);

                    //Add DataSource module
                    ManagementPackModuleType dsModType;
                    ManagementPackDataSourceModule dsModule;

                    dsModType = mg.GetMonitoringModuleTypes(“Microsoft.Windows.EventProvider”)[0];
                    dsModule = new ManagementPackDataSourceModule(rule, “DS”);
                    dsModule.TypeID = (ManagementPackDataSourceModuleType)dsModType;
                    dsModule.Configuration = xmlCfg;
                    rule.DataSourceCollection.Add(dsModule);

                    //Add Alert Write Action module
                    ManagementPackModuleType alertModuleType = mg.GetMonitoringModuleTypes(“System.Health.GenerateAlert”)[0];
                    ManagementPackWriteActionModule alertModule = new ManagementPackWriteActionModule(rule, “Alert”);
                    alertModule.DisplayName = “Alert”;
                    alertModule.TypeID = (ManagementPackWriteActionModuleType)alertModuleType;
                    StringBuilder sb = new StringBuilder();
                    sb.Append(“<Priority>1</Priority>”);
                    sb.Append(“<Severity>2</Severity>”);
                    sb.Append(“<AlertName>” + AcctAlertName + “</AlertName>”);
                    sb.Append(“<AlertDescription />”);
                    sb.Append(“<AlertOwner />”);

                    string AlertMsgID = CreateStringResource(mp, rule, “Event Description: {0}”);
                    sb.Append(“<AlertMessageId>$MPElement[Name=\"" + AlertMsgID + "\"]$</AlertMessageId>”);
                    
                    sb.Append(“<AlertParameters>”);
                        sb.Append(“<AlertParameter1>$Data/EventDescription$</AlertParameter1>”);
                    sb.Append(“</AlertParameters>”);
                    sb.Append(“<Suppression />”);
                    sb.Append(“<Custom1 />”);
                    sb.Append(“<Custom2 />”);
                    sb.Append(“<Custom3 />”);
                    sb.Append(“<Custom4 />”);
                    sb.Append(“<Custom5 />”);
                    sb.Append(“<Custom6 />”);
                    sb.Append(“<Custom7 />”);
                    sb.Append(“<Custom8 />”);
                    sb.Append(“<Custom9 />”);
                    sb.Append(“<Custom10 />”);
                    alertModule.Configuration = sb.ToString();
                    rule.WriteActionCollection.Add(alertModule);

                    //commit changes to MP
                    mp.Verify();
                    mp.AcceptChanges();
                    
                    ReturnXML.AddData(“<Rule>” + rule.Id + “</Rule>”);
                    // Set variables to pass to Auditing
                    String MethodName = new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name;
                    string oldVal = string.Empty;
                    string NewVal = string.Empty;
                    string NamePath = rule.DisplayName;

                    this.WriteAuditTrail(MethodName, NamePath, oldVal, NewVal, Ticket, UserID, “SCOM”);
                }//if mp not null
    
                //set status
                ReturnXML.SetStatus(WebServiceXML.ServiceStatus.Succeeded);
            }
            catch (Exception ex)
            {
                EventLogWriter.LogEvent(ex);
                ReturnXML.SetStatus(WebServiceXML.ServiceStatus.Failed, GenericErrorMsg);
            }

            return ReturnXML.Root;
        }//CreateEventRule

        [WebMethod]
        public XmlDocument UpdateEventRule(string DC, int Account, string RuleGUID,
                                            string AlertText, string EventLogName,
                                            string EventIDExpression, string EventSourceExpression,
                                            string EventLevelExpression, string EventDescriptionExpression,
                                            string Ticket,
                                            string UserID)
        {
            WebServiceXML ReturnXML = new WebServiceXML();
            try
            {
                string AcctRuleName = string.Empty;
                string AcctAlertName = string.Empty;

                if (AlertText.StartsWith(Account.ToString())) //does the alert text begin with the acct# ??
                {
                    AcctAlertName = AlertText; //yes – do nothing
                }
                else
                {
                    AcctAlertName = Account.ToString() + ” – ” + AlertText; //else add acct# to rule name
                }

                string mpRuleName = “WebServiceRule” + RuleGUID;

                //connect to the Management Group
                ConnectManagementGroup(DC);

                ManagementPack mp = mg.GetManagementPacks(“rs” + Account.ToString())[0];
                ManagementPackRule rule = mg.GetMonitoringRule(new Guid(RuleGUID));
                rule.Description += “\r\n” + DateTime.Now.ToShortDateString() + ” – #” + Ticket + ” Rule updated by ” + UserID + ” via ssPortal”;
                rule.DisplayName = AcctAlertName;

                string xmlCfg = CreateConfigXML(EventLogName, EventIDExpression, EventSourceExpression, EventLevelExpression, EventDescriptionExpression);

                rule.DataSourceCollection[0].Configuration = xmlCfg;

                //update Alert Write Action module
                ManagementPackModuleType alertModuleType = mg.GetMonitoringModuleTypes(“System.Health.GenerateAlert”)[0];
                ManagementPackWriteActionModule alertModule = new ManagementPackWriteActionModule(rule, “Alert”);
                alertModule.DisplayName = “Alert”;
                alertModule.TypeID = (ManagementPackWriteActionModuleType)alertModuleType;
                StringBuilder sb = new StringBuilder();
                sb.Append(“<Priority>1</Priority>”);
                sb.Append(“<Severity>2</Severity>”);
                sb.Append(“<AlertName>” + AcctAlertName + “</AlertName>”);

                string AlertMsgID = CreateStringResource(mp, rule, “Event Description: {0}”);
                sb.Append(“<AlertMessageId>$MPElement[Name=" + AlertMsgID + "]$</AlertMessageId>”);

                sb.Append(“<AlertOwner />”);
                sb.Append(“<AlertMessageId />”);
                sb.Append(“<AlertParameters>”);
                sb.Append(“<AlertParameter1>$Data/EventDescription$</AlertParameter1>”);
                sb.Append(“</AlertParameters>”);
                sb.Append(“<Suppression />”);
                sb.Append(“<Custom1 />”);
                sb.Append(“<Custom2 />”);
                sb.Append(“<Custom3 />”);
                sb.Append(“<Custom4 />”);
                sb.Append(“<Custom5 />”);
                sb.Append(“<Custom6 />”);
                sb.Append(“<Custom7 />”);
                sb.Append(“<Custom8 />”);
                sb.Append(“<Custom9 />”);
                sb.Append(“<Custom10 />”);

                alertModule.Configuration = sb.ToString();

                rule.WriteActionCollection.Clear(); //erase old module
                rule.WriteActionCollection.Add(alertModule); //rewrite the new one

                rule.Status = ManagementPackElementStatus.PendingUpdate;

                //commit changes to MP
                mp.Verify();
                mp.AcceptChanges();

                ReturnXML.AddData(“<Rule>” + rule.Id + “</Rule>”);

                // Set variables to pass to Auditing
                String MethodName = new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name;
                string oldVal = string.Empty;
                string NewVal = string.Empty;
                string NamePath = rule.DisplayName;

                this.WriteAuditTrail(MethodName, NamePath, oldVal, NewVal, Ticket, UserID, “SCOM”);

                //set status
                ReturnXML.SetStatus(WebServiceXML.ServiceStatus.Succeeded);
            }
            catch (Exception ex)
            {
                EventLogWriter.LogEvent(ex);
                ReturnXML.SetStatus(WebServiceXML.ServiceStatus.Failed, GenericErrorMsg);
            }

            return ReturnXML.Root;
        }//UpdateEventRule

        private string CreateStringResource(ManagementPack mp, ManagementPackRule r, string AlertText)
        {
            ManagementPackStringResource msr = new ManagementPackStringResource(mp, r.Name + “.AlertMessage”);
            msr.DisplayName = r.DisplayName;
            msr.Description = AlertText;
            return msr.Name;
        }
        private string CreateConfigXML(string EvtLog, string EventIDExpr, string EventSourceExpr,
                                       string EventLevelExpr, string EventDescriptionExpr)
        {
            StringBuilder xmlString = new StringBuilder();

            xmlString.Append(@”<ComputerName>$Target/Property[Type=""Windows!Microsoft.Windows.Computer""]/NetworkName$</ComputerName>”);
            xmlString.Append(“<LogName>” + EvtLog + “</LogName>”);
            int expStart = xmlString.Length;
            int expCount = 0;
            if (EventIDExpr != string.Empty)
            {
                xmlString.Append(CreateExpressionTree(“UnsignedInteger”, “EventDisplayNumber”, EventIDExpr));
                expCount++;
            }
            if (EventSourceExpr != string.Empty)
            {
                xmlString.Append(CreateExpressionTree(“String”, “PublisherName”, EventSourceExpr));
                expCount++;
            }
            if (EventLevelExpr != string.Empty)
            {
                xmlString.Append(CreateExpressionTree(“Integer”, “EventLevel”, EventLevelExpr));
                expCount++;
            }
            if (EventDescriptionExpr != string.Empty)
            {
                xmlString.Append(CreateExpressionTree(“String”, “EventDescription”, EventDescriptionExpr));
                expCount++;
            }

            if (expCount == 0)
            {
                xmlString.Append(“<Expression />”);
            }
            else
            {
                if (expCount > 1) //if more than 1 expression, wrap the expressions inside an <AND> expression
                {
                    xmlString.Insert(expStart, “<Expression><And>”);
                    xmlString.Append(“</And></Expression>”);
                }
            }

            
            return xmlString.ToString();
        }

        private string CreateExpressionTree(string vType, string vName, string expr)
        {
            string LeftOp = @”<XPathQuery Type=””” + vType + @”””>” + vName + “</XPathQuery>”;
            string Op = expr.Substring(0, expr.IndexOf(” “));
            string RightOp = expr.Substring(expr.IndexOf(” “)+1);
            StringBuilder sb = new StringBuilder();

            switch (Op)
            {
                case “Equal”:
                case “NotEqual”:
                case “Greater”:
                case “GreaterEqual”:
                case “Less”:
                case “LessEqual”:
                                sb.Append(“<Expression><SimpleExpression>”);
                                sb.Append(“<ValueExpression>” + LeftOp + “</ValueExpression>”);
                                    sb.Append(“<Operator>” + Op + “</Operator>”);
                                sb.Append(“<ValueExpression>”);
                                    sb.Append(@”<Value Type=””” + vType + @”””>” + RightOp + “</Value>”);
                                sb.Append(“</ValueExpression></SimpleExpression></Expression>”);
                                break;

                case “ContainsSubstring”:
                case “DoesNotContainSubstring”:
                case “MatchesWildcard”:
                case “DoesNotMatchWildcard”:
                                sb.Append(“<Expression><RegExExpression>”);
                                sb.Append(“<ValueExpression>” + LeftOp + “</ValueExpression>”);
                                sb.Append(“<Operator>” + Op + “</Operator>”);
                                sb.Append(@”<Pattern>” + RightOp + “</Pattern>”);
                                sb.Append(“</RegExExpression></Expression>”);
                                break;

                default:
                                sb.Append(“Invalid operator: <” + Op + “>”);
                                break;
            }//switch

            return sb.ToString();
        }//CreateExpressionTree

        [WebMethod]
        public XmlDocument EnableRule(string DC, string RuleGUID, string ServerGUID, string Ticket, string UserID)
        {
            WebServiceXML ReturnXML = new WebServiceXML();
            List<string> pNodes = new List<string>();

            try
            {
                ConnectManagementGroup(DC);
                MonitoringObject objServer = mg.GetMonitoringObject(new Guid(ServerGUID));
                ManagementPackRule rule = mg.GetMonitoringRule(new Guid(RuleGUID));
                ManagementPack mp = rule.GetManagementPack();

                MonitoringObjectGenericCriteria moCriteria;

                moCriteria = new MonitoringObjectGenericCriteria(“DisplayName like ‘%” + objServer.DisplayName + “%'”);
                MonitoringObject WinComputerObject = mg.GetMonitoringObjects(moCriteria, WinComputerClass)[0];
                EnableOverride(mg, rule, WinComputerObject.Id, Ticket, UserID);

                mp.Verify();
                mp.AcceptChanges();

                // Set variables to pass to Auditing
                String MethodName = new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name;
                string oldVal = string.Empty;
                string NewVal = objServer.DisplayName;
                string NamePath = rule.DisplayName;

                this.WriteAuditTrail(MethodName, NamePath, oldVal, NewVal, Ticket, UserID, “SCOM”);

                //set status
                ReturnXML.SetStatus(WebServiceXML.ServiceStatus.Succeeded);
            }
            catch (Exception ex)
            {
                EventLogWriter.LogEvent(ex);
                ReturnXML.SetStatus(WebServiceXML.ServiceStatus.Failed, ex.Message);
            }
            return ReturnXML.Root;

        }//EnableRule

        private void EnableOverride(ManagementGroup mg, ManagementPackRule rule, Guid svrGUID, string ticket, string user)
        {
            ManagementPack mp = rule.GetManagementPack();
            string OverrideName = “OverrideForRule” + rule.Name + svrGUID.ToString().Replace(“-“,string.Empty);

            ManagementPackRulePropertyOverride ov = new ManagementPackRulePropertyOverride(mp, OverrideName);
            ov.DisplayName = “Override for Rule: ” + rule.DisplayName;
            ov.Rule = rule;
            ov.Description += “\r\n” + DateTime.Now.ToShortDateString() + ” – #” + ticket + ” Enabled by ” + user + ” via ssPortal”;
            ov.Property = ManagementPackWorkflowProperty.Enabled;
            ov.Value = “true”;
            ov.Context =WinComputerClass;
            ov.ContextInstance = svrGUID;
        }//EnableRule

        [WebMethod]
        public XmlDocument DisableRule(string DC, string RuleGuid, string ServerGUID,string Ticket, string UserID)
        {
            WebServiceXML ReturnXML = new WebServiceXML();

            try
            {
                ConnectManagementGroup(DC);

                ManagementPackRulePropertyOverride ov;
                ManagementPackRule rule = mg.GetMonitoringRule(new Guid(RuleGuid));
                ManagementPack mp = rule.GetManagementPack();
                MonitoringObject objServer = mg.GetMonitoringObject(new Guid(ServerGUID));
                MonitoringObjectGenericCriteria monCriteria;

                string crit = “DisplayName like ‘%” + objServer.DisplayName + “%’ “;
                monCriteria = new MonitoringObjectGenericCriteria(crit);
                ReadOnlyCollection<MonitoringObject> WinComputerObjects = mg.GetMonitoringObjects(monCriteria, WinComputerClass);

                crit = “TargetId = ‘” + RuleGuid + “‘ AND ContextObjectId = ‘” + WinComputerObjects[0].Id.ToString() + “‘ “;
                MonitoringOverrideCriteria moCriteria = new MonitoringOverrideCriteria(crit);
                ReadOnlyCollection<ManagementPackOverride> RuleOverrides = mg.GetMonitoringOverrides(moCriteria);
                
                foreach (ManagementPackRuleOverride ruleOverride in RuleOverrides)
                {
                    if (ruleOverride is ManagementPackRulePropertyOverride)
                    {
                        ov = (ManagementPackRulePropertyOverride)ruleOverride;
                        ov.Value = “false”;
                        ov.Description += “\r\n” + DateTime.Now.ToShortDateString() + ” – #” + Ticket + ” Disabled by ” + UserID + ” via ssPortal”;
                        ov.Status = ManagementPackElementStatus.PendingUpdate;
                    }
                }

                mp.Verify();
                mp.AcceptChanges();

                // Set variables to pass to Auditing
                String MethodName = new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name;
                string oldVal = objServer.DisplayName;
                string NewVal = string.Empty;
                string NamePath = rule.DisplayName;

                this.WriteAuditTrail(MethodName, NamePath, oldVal, NewVal, Ticket, UserID, “SCOM”);

                //set status
                ReturnXML.SetStatus(WebServiceXML.ServiceStatus.Succeeded);
            }
            catch (Exception ex)
            {
                EventLogWriter.LogEvent(ex);
                ReturnXML.SetStatus(WebServiceXML.ServiceStatus.Failed, ex.Message);
            }
            return ReturnXML.Root;

        }//DisableRule

        [WebMethod(cacheDuration=600]
        public XmlDocument GetEventRules(string DC, int Account)
        {
            WebServiceXML ReturnXML = new WebServiceXML();
            try
            {
                ConnectManagementGroup(DC);
                ManagementPack mp = mg.GetManagementPacks(“rs” + Account.ToString())[0];
                GetRuleOverrides(mg, mp); //load rule overrides into list for faster lookups
                if (mp != null)
                {
                    ManagementPackElementCollection<ManagementPackRule> Rules = mp.GetRules();
                    StringBuilder sbXML = new StringBuilder();
                    foreach (ManagementPackRule rule in Rules)
                    {
                        if (rule.Name.Contains(“WebServiceRule”)) //only interested in custom rules created by the WebService
                        {
                            sbXML.Append(@”<Rule guid=””” + rule.Id + @”””>”);
                            sbXML.Append(“<AlertText>” + rule.DisplayName + “</AlertText>”);
                            sbXML.Append(“<Criteria>”);
                            sbXML.Append(rule.DataSourceCollection[0].Configuration);
                            sbXML.Append(“</Criteria>”);
                            sbXML.Append(“<Overrides>”);
                            sbXML.Append(GetOverridesForRule(rule.Id));
                            sbXML.Append(“</Overrides>”);
                            sbXML.Append(“</Rule>”);
                        }
                    }
                    //set status
                    ReturnXML.AddData(sbXML.ToString());
                }//if mp is not null
                ReturnXML.SetStatus(WebServiceXML.ServiceStatus.Succeeded);
             }
            catch (Microsoft.EnterpriseManagement.Common.ObjectNotFoundException onf)
            {
                ReturnXML.SetStatus(WebServiceXML.ServiceStatus.Failed, “Custom Management Pack for account ” + Account.ToString() + ” was not found. Create a custom MP, then try this page again”);
            }
            catch (Exception ex)
            {
                EventLogWriter.LogEvent(ex);
                ReturnXML.SetStatus(WebServiceXML.ServiceStatus.Failed, ex.Message);
            }
            return ReturnXML.Root;

        }//EnableRule

        private void GetRuleOverrides(ManagementGroup mg, ManagementPack mp)
        {
            ManagementPackElementCollection<ManagementPackOverride> overrides = mp.GetOverrides();
            foreach (ManagementPackOverride mpOverride in overrides)
            {
                if (mpOverride is ManagementPackRulePropertyOverride)
                {
                    ManagementPackRulePropertyOverride ruleOV = (ManagementPackRulePropertyOverride)mpOverride;
                    if (ruleOV.Property == ManagementPackWorkflowProperty.Enabled)
                        lstRuleOverrides.Add(ruleOV);
                }
            }
        }
  
        private string GetOverridesForRule(Guid ruleID)
        {
            MonitoringObject svrObj;
            StringBuilder sbOV = new StringBuilder();
            List<string> serverList = new List<string>();

            var res = from o in lstRuleOverrides
                      where o.Rule.Id == ruleID
                      select o;

            foreach(var ov in res)
            {
                ManagementPackRulePropertyOverride ruleOV = (ManagementPackRulePropertyOverride)ov;
                svrObj = mg.GetMonitoringObject((Guid)ruleOV.ContextInstance);

                if (!serverList.Contains(svrObj.DisplayName))
                {
                    MonitoringObjectGenericCriteria moCriteria = new MonitoringObjectGenericCriteria(“DisplayName like ‘%” + svrObj.DisplayName + “%'”);
                    ReadOnlyCollection<MonitoringObject> objList = mg.GetMonitoringObjects(moCriteria,WinComputerClass);

                    if (objList.Count > 0)
                    {
                        sbOV.Append(“<Override id=\”” + ruleOV.Id.ToString() + “\”>”);
                        sbOV.Append(“<Server enabled=\”” + ruleOV.Value + “\” id=\”” + objList[0].Id.ToString() + “\”>” + svrObj.DisplayName + “</Server>”);
                        sbOV.Append(“</Override>”);
                        serverList.Add(svrObj.DisplayName);
                    }
                }
            }//foreach

            return sbOV.ToString();
        }
#endregion

ssPortal: Create/Update a Service State Monitor(Part 2)

March 1, 2011 Leave a comment

After entering the usual DC and Account number parameters, the Service State Monitors page displays a list of Monitored Services. This is a list of service Display Names that have custom service state monitors defined for them. Clicking on a service displays the details of the monitor: the actual service name, the display name and a list of computers that have enable overrides defined.

Clicking the New Monitor button displays an empty form to create a new monitor. The Service Name is the shortname of the service(as found in the registry under HKLM\SYSTEM\CurrentControlSet\Services). The Display Name, for simplicity, should match the service Display Name, although it doesn’t have to. The text in the Display Name is used to build the alert text, which is “<Display Name> service is not running”. In the sample screen shot below, I could have entered “SCOM Agent” in the Display Name and the monitor would alert with the text “SCOM Agent service is not running”.

The Monitor is created in a disabled state. Adding a server to a monitor is just creating an enable override. Removing a server from a monitor sets the override’s enabled property to false, since the SDK does not have any methods to delete anything.

Service State Monitors

ServiceMonitor.aspx

<%@ Page Title=”” Language=”C#” MasterPageFile=”~/Site.Master” AutoEventWireup=”true”
    CodeBehind=”ServiceMonitor.aspx.cs” Inherits=”SSPortal.SCOM.ServiceMonitor” %>

<%@ Register Assembly=”AjaxControlToolkit” Namespace=”AjaxControlToolkit” TagPrefix=”asp” %>
<asp:Content ID=”Content1″ ContentPlaceHolderID=”PageContents” runat=”server”>
    <asp:XmlDataSource runat=”server” ID=”xmlSCOM” DataFile=”~/App_Data/SCOMRMS.xml” />
    <asp:ToolkitScriptManager ID=”ToolkitScriptManager1″ runat=”server” />
    <h3>
        Service State Monitors</h3>
    <asp:UpdatePanel ID=”UpdatePanel” runat=”server” UpdateMode=”Conditional” RenderMode=”Inline”>
        <ContentTemplate>
            <div id=”inDiv”>
                DC:
                <asp:DropDownList ID=”ddlDC” runat=”server” DataSourceID=”xmlSCOM” DataTextField=”dc”
                    DataValueField=”dc” ToolTip=”The Data Center where the Account is housed. The DC is used to determine which SCOM server to connect to.” />
                Account:
                <asp:TextBox ID=”txtAccount” runat=”server” Width=”50px” ToolTip=”The account number you want to create/modify service monitors for” />
                <asp:Button ID=”Button1″ runat=”server” Text=”Submit” OnClick=”Button1_Click” />
                <asp:UpdateProgress ID=”UpdateProgressPanel” AssociatedUpdatePanelID=”UpdatePanel”
                    runat=”server” DynamicLayout=”false”>
                    <ProgressTemplate>
                        <asp:Image ID=”LoadingSpinner” runat=”server” ImageUrl=”~/images/loading.gif” Height=”24px”
                            Width=”24px” ImageAlign=”Top” />
                    </ProgressTemplate>
                </asp:UpdateProgress>
            </div>
            <asp:Label ID=”lblErrMsg” runat=”server” ForeColor=”Red”> </asp:Label>
            <asp:CompareValidator ID=”CompareValidator1″ runat=”server” ErrorMessage=”Select a DC from the list<br/>”
                ControlToValidate=”ddlDC” ValueToCompare=’Select a DC…’ Display=”Dynamic” Operator=”NotEqual”></asp:CompareValidator>
            <asp:RequiredFieldValidator ID=”RequiredFieldValidator1″ runat=”server” ErrorMessage=”Account Number is required<br/>”
                ControlToValidate=”txtAccount” Display=”Dynamic”></asp:RequiredFieldValidator>
            <asp:RangeValidator ID=”RangeValidator1″ runat=”server” ErrorMessage=”Invalid data in Account number<br/>”
                ControlToValidate=”txtAccount” Type=”Integer” MinimumValue=”000000″ MaximumValue=”999999″
                Display=”Dynamic”></asp:RangeValidator>
            <hr />
            <asp:Label runat=”server” ID=”lblNote” Visible=”false”>
                <em>
                    The default SCOM monitoring will alert if the Windows Service Control Manager reports that a service terminates "unexpectedly".<br />
                    If someone stops the service in the Services console(or with the NET STOP command), the alert will not be generated.<br />
                    <br />
                    If you want an alert any time the service is not in a RUNNING state for any reason, incuding manual stops, then create a custom Service State Monitor for the service.<br />
                    NOTE: Only services that have a Start type of <b>Automatic</b> are monitored by the Service State Monitor
                </em>
            </asp:Label>
            <asp:Table runat=”server” ID=”tblMonitors” Width=”1020px” Visible=”false” CellPadding=”0″
                CellSpacing=”0″>
                <asp:TableRow>
                    <asp:TableCell VerticalAlign=”Top” HorizontalAlign=”left” Width=”310px”>
                        <div style=”vertical-align: top; height: 350px; overflow: auto; width: 300px;”>
                            <b>Monitored Services</b><br />
                            <asp:ListBox ID=”lstMonitors” runat=”server” Width=”280px” AutoPostBack=”true” OnSelectedIndexChanged=”lstMonitors_SelectedIndexChanged” Rows=”19″ ToolTip=”This is the list of the Services that have monitors defined for them. Click on the service name to see the monitor details.”></asp:ListBox>
                        </div>
                        <asp:Button runat=”server” ID=”Button2″ OnClick=”btnNewMonitor_Click” Text=”New Monitor” />
                    </asp:TableCell>
                    <asp:TableCell VerticalAlign=”Top” HorizontalAlign=”Center” Width=”710px”>
                        <br />
                        <asp:Table runat=”server” ID=”tblDetails” BorderWidth=”1″ BorderStyle=”Solid” Visible=”false”
                            CssClass=”TblRowOdd”>
                            <asp:TableRow>
                                <asp:TableCell Width=”500px”>
                                    <asp:Label runat=”server” ID=”lblMonitorID” Width=”435px”></asp:Label></asp:TableCell>
                                <asp:TableCell Width=”210px”> </asp:TableCell>
                            </asp:TableRow>
                            <asp:TableRow>
                                <asp:TableCell>
                                    <asp:Table runat=”server” ID=”tblMonitorCriteria” Width=”500px” BorderStyle=”Solid”
                                        BorderWidth=”1″>
                                        <asp:TableRow>
                                            <asp:TableCell Width=”130px”>Service Name</asp:TableCell>
                                            <asp:TableCell Width=”180px”>
                                                <asp:TextBox runat=”server” ID=”txtServiceName” OnTextChanged=”Form_DataChanged”
                                                    Width=”180px” ToolTip=”This is the ‘internal’ name of the service; not the display name that you see in the Services console. Only services that have a start type of AUTOMATIC will be monitored.”></asp:TextBox></asp:TableCell>
                                            <asp:TableCell Width=”200px”> </asp:TableCell>
                                        </asp:TableRow>
                                        <asp:TableRow>
                                            <asp:TableCell Width=”130px”>Display Name</asp:TableCell>
                                            <asp:TableCell Width=”180px”>
                                                <asp:TextBox runat=”server” ID=”txtDisplayName” OnTextChanged=”Form_DataChanged”
                                                    Width=”180px” ToolTip=”This is a user-friendly name for the service. When this monitor triggers an alert, the alert text will be ‘<Display Name> service is not running’. It does not neccessarily have to match what is displayed in the Services console, but to keep things consistent it probably should match.”></asp:TextBox></asp:TableCell>
                                            <asp:TableCell Width=”200px”> </asp:TableCell>
                                        </asp:TableRow>
                                        <asp:TableRow>
                                            <asp:TableCell> </asp:TableCell>
                                            <asp:TableCell> </asp:TableCell>
                                            <asp:TableCell> </asp:TableCell>
                                        </asp:TableRow>
                                        <asp:TableRow>
                                            <asp:TableCell ColumnSpan=”3″>Apply to these servers:</asp:TableCell>
                                        </asp:TableRow>
                                        <asp:TableRow>
                                            <asp:TableCell> </asp:TableCell>
                                            <asp:TableCell ColumnSpan=”2″>
                                                <asp:ListBox runat=”server” ID=”lstMonitorServers” Width=”380px” Rows=”10″ SelectionMode=”Multiple”
                                                    ToolTip=”This is the list of servers that the service monitor will be applied to.”>
                                                </asp:ListBox>
                                                <br />
                                                <br />
                                                <asp:Button ID=”btnRemoveServer” runat=”server” OnClick=”btnRemoveServer_Click” Text=”Remove server from rule” />
                                            </asp:TableCell>
                                        </asp:TableRow>
                                    </asp:Table>
                                </asp:TableCell>
                                <asp:TableCell VerticalAlign=”Top”>
                                    Available Servers
                                    <asp:ListBox runat=”server” ID=”lstAllServers” Rows=”10″ Width=”210px” SelectionMode=”Multiple”
                                        ToolTip=”This is the list of all servers in the account that are running the SCOM agent. If a server does not appear in this list and it is running the SCOM agent, check that the HKLM\Software\Rackspace Registry key exists and that the CustomerNumber value is populated with the correct account number. Select one or more servers and click the <–Add Server(s) button below to add the server(s) to the list of servers the rule is applied to.”>
                                    </asp:ListBox>
                                    <asp:Button ID=”btnAddServer” runat=”server” Text=”<– Add server(s)” OnClick=”btnAddServer_Click” />
                                </asp:TableCell>
                            </asp:TableRow>
                            <asp:TableRow>
                                <asp:TableCell>
                                    Ticket# <asp:TextBox ID=”txtTicket” runat=”server” Width=”12em”></asp:TextBox>(required for committing changes)</asp:TableCell>
                            </asp:TableRow>
                        </asp:Table>
                        <asp:TableCell>
                            <asp:Button ID=”btnCommit” runat=”server” Text=”Commit Changes” OnClientClick=”validate()”
                                OnClick=”btnCommit_Click” />
                            <asp:Button ID=”btnReset” runat=”server” Text=”Reset” OnClick=”lstMonitors_SelectedIndexChanged” />
                        </asp:TableCell>
                    </asp:TableCell>
                </asp:TableRow>
            </asp:Table>
        </ContentTemplate>
    </asp:UpdatePanel>
</asp:Content>

ServiceMonitor.aspx.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using LogWriter;
using ListBoxSorter;
using ssPortalWebClient;

namespace SSPortal.SCOM
{
    public partial class ServiceMonitor : System.Web.UI.Page
    {
        protected DataTable dtMonitors = new DataTable();
        protected DataTable dtMonitorservers = new DataTable();
        protected DataTable dtMonitorServersCurrent = new DataTable();
        protected DataTable dtMonitorserversOriginal = new DataTable();
        protected DataTable dtAllServers = new DataTable();
        protected string UserName;
        protected bool DataChanged = false;
        protected bool ServerListChanged = false;

        //Event Handlers
        #region Event Handlers
        protected void Page_Load(object sender, EventArgs e)
        {
#if __PRODUCTION__
            NetworkCredential creds = (NetworkCredential)Session["Credentials"];
            UserName = creds.UserName;
#else
            UserName = “Test.User”;
#endif
            if (!IsPostBack)
            {
                ddlDC.Focus();
                lblErrMsg.Text = string.Empty;
                lblNote.Visible = true;
            }
            Page.Form.DefaultButton = Button1.UniqueID;
            if (Session["DataChanged"] != null) DataChanged = (bool)Session["DataChanged"];
            if (Session["ServerListChanged"] != null) ServerListChanged = (bool)Session["ServerListChanged"];
        }
        protected void Button1_Click(object sender, EventArgs e)
        {
            lblErrMsg.Text = string.Empty;
            lblNote.Visible = false;
            tblMonitors.Visible = false;
            tblDetails.Visible = false;
            btnCommit.Visible = false;
            btnReset.Visible = false;
            dtMonitors.Clear();
            dtMonitorservers.Clear();
            lstMonitors.Items.Clear();
           try
            {
                LoadData(); //load web service data into datatables
                if (lstMonitors.Items.Count == 0)
                    lstMonitors.Visible = false;
                else
                    lstMonitors.Visible = true;
              
            }//try
            catch (Exception ex)
            {
                lblErrMsg.Text = EventLogWriter.GenericErrorMsg;
                EventLogWriter.LogEvent(ex);
            }
        }//Button1_click
        protected void lstMonitors_SelectedIndexChanged(object sender, EventArgs e)
        {
            lblErrMsg.Text = string.Empty;
            dtMonitors = (DataTable)Session["dtMonitors"];
            DataRow dr = dtMonitors.Select(“MonitorGuid='” + lstMonitors.SelectedValue + “‘”)[0];

            lblMonitorID.Text = “ID: ” + dr["MonitorGuid"].ToString();
            txtServiceName.Text = dr["ServiceName"].ToString();
            txtDisplayName.Text = dr["DisplayName"].ToString();
            txtTicket.Text = string.Empty;

            dtMonitorservers = (DataTable)Session["MonitorServersTable"];

            DataView dv = new DataView(dtMonitorservers, “MonitorGuid='” + lstMonitors.SelectedValue + “‘”, “ServerName”, DataViewRowState.CurrentRows);

            dtMonitorServersCurrent = dv.ToTable();
            dtMonitorserversOriginal = dv.ToTable();

            SavetoSession(“CurrentMonitorServers”, dtMonitorServersCurrent);
            SavetoSession(“OriginalMonitorServers”, dtMonitorserversOriginal);

            lstMonitorServers.DataSource = dtMonitorServersCurrent.DefaultView;
            lstMonitorServers.DataTextField = “ServerName”;
            lstMonitorServers.DataValueField = “ServerGuid”;
            lstMonitorServers.DataBind();
            if (lstMonitorServers.Items.Count == 0)
            {
                btnRemoveServer.Enabled = false; //so user doesn’t try to remove something that is not there
            }
            else
            {
                btnRemoveServer.Enabled = true;
            }

            btnCommit.Text = “Commit Monitor Changes”;
            btnCommit.Visible = true;
            btnReset.Visible = true;
            tblDetails.Visible = true;
        }
        protected void btnNewMonitor_Click(object sender, EventArgs e)
        {
            lblErrMsg.Text = string.Empty;
            InitDetailForm(); //clear all the fields
            
            dtMonitorServersCurrent = (DataTable)Session["CurrentMonitorServers"];
            if (dtMonitorServersCurrent != null)
                dtMonitorServersCurrent.Clear();

            dtMonitorserversOriginal = (DataTable)Session["OriginalMonitorServers"];
            if (dtMonitorserversOriginal != null)
                dtMonitorserversOriginal.Clear();
        }
        protected void btnCommit_Click(object sender, EventArgs e)
        {
            try
            {
                lblErrMsg.Text = string.Empty;
                string monitorID = string.Empty;

                if (ValidData())
                {
                    dtMonitors = (DataTable)Session["dtMonitors"];
                    if (btnCommit.Text == “Commit New Monitor”) //are we adding a new monitor?
                    {
                        if (DataChanged)
                        {
                            monitorID = AddUpdateMonitor(“Create”);
                            btnCommit.Text = “Commit Monitor Changes”;
                            dtMonitors.Rows.Add(monitorID, txtServiceName.Text, txtDisplayName.Text);
                            dtMonitors.AcceptChanges();
                            if ((monitorID != string.Empty) && (ServerListChanged))
                                ApplyServersToMonitor(monitorID);

                            AddToARIC();
                        }
                    }
                    else //updating an existing monitor
                    {
                        if (DataChanged)
                        {
                            monitorID = AddUpdateMonitor(“Update”);
                            DataRow[] rows = dtMonitors.Select(“MonitorGuid='” + monitorID +”‘”);
                            rows[0]["ServiceName"] = txtServiceName.Text;
                            rows[0]["DisplayName"] = txtDisplayName.Text;
                            dtMonitors.AcceptChanges();
                        
                            if (lstMonitors.SelectedItem.Text != txtDisplayName.Text)
                                UpdateARIC();
                        }
                        if (ServerListChanged)
                            ApplyServersToMonitor(lblMonitorID.Text.Substring(4));
                    }

                    if ((DataChanged) || (ServerListChanged)) //if anything was changed
                    {

                        //rebind the listbox
                        DataView dv = new DataView(dtMonitors);
                        dv.Sort = “DisplayName”;
                        lstMonitors.DataSource = dv;
                        lstMonitors.DataTextField = “DisplayName”;
                        lstMonitors.DataValueField = “MonitorGuid”;
                        lstMonitors.DataBind();
                        lstMonitors.SelectedIndex =dv.Find(txtDisplayName.Text);

                        //reset the flags
                        DataChanged = false;
                        ServerListChanged = false;

                        //save eveything
                        SavetoSession(“dtMonitors”, dtMonitors);
                        SavetoSession(“DataChanged”, DataChanged);
                        SavetoSession(“ServerListChanged”, ServerListChanged);
                    }
                    txtTicket.Text = string.Empty;
                }
            }
            catch (Exception ex)
            {
                lblErrMsg.Text = EventLogWriter.GenericErrorMsg;
                EventLogWriter.LogEvent(ex);
            }
        }
        protected void btnAddServer_Click(object sender, EventArgs e)
        {
            DataRow dr, dr2;
            ServerListChanged = true;
            SavetoSession(“ServerListChanged”, ServerListChanged);

            if (Session["CurrentMonitorServers"] != null)
                dtMonitorServersCurrent = (DataTable)Session["CurrentMonitorServers"];

            if (Session["MonitorServersTable"] != null)
                dtMonitorservers = (DataTable)Session["MonitorServersTable"];

            for (int i=0;i<lstAllServers.Items.Count; i++) //loop through the listbox
            {
                if (lstAllServers.Items[i].Selected) //if the row is selected
                {
                    dr = dtMonitorServersCurrent.NewRow();
                    if (lblMonitorID.Text == string.Empty)
                    {
                        dr["MonitorGuid"] = string.Empty;
                    }
                    else
                    {
                        dr["MonitorGuid"] = lblMonitorID.Text.Substring(4);
                    }
                    dr["OverrideGuid"] = string.Empty;
                    dr["ServerName"] = lstAllServers.Items[i].Text;
                    dr["ServerGuid"] = lstAllServers.Items[i].Value;

                    DataRow[] existingRows = dtMonitorServersCurrent.Select(“ServerGuid = ‘” + lstAllServers.Items[i].Value + “‘”);

                    if (existingRows.Length == 0) //not already found in current list
                    {
                        dtMonitorServersCurrent.Rows.Add(dr);
                        dr2 = dtMonitorservers.NewRow();
                        dr2.ItemArray = dr.ItemArray;
                        dtMonitorservers.Rows.Add(dr2);
                        btnRemoveServer.Enabled = true; //enable so it can be removed
                    }
                }//if li.selected
            }//for
            SavetoSession(“CurrentMonitorServers”, dtMonitorServersCurrent);
            SavetoSession(“MonitorServersTable”, dtMonitorservers);
            lstMonitorServers.DataSource = dtMonitorServersCurrent.DefaultView;
            lstMonitorServers.DataTextField = “ServerName”;
            lstMonitorServers.DataValueField = “ServerGuid”;
            lstMonitorServers.DataBind();
        }
        protected void btnRemoveServer_Click(object sender, EventArgs e)
        {
            ServerListChanged = true;
            SavetoSession(“ServerListChanged”, ServerListChanged);
            
            if (Session["CurrentMonitorServers"] != null)
                dtMonitorServersCurrent = (DataTable)Session["CurrentMonitorServers"];

            if (Session["MonitorServersTable"] != null)
                dtMonitorservers = (DataTable)Session["MonitorServersTable"];

            for (int i = 0; i < lstMonitorServers.Items.Count; i++) //loop through the listbox
            {
                if (lstMonitorServers.Items[i].Selected) //if the row is selected
                {
                    DataRow[] existingRows = dtMonitorServersCurrent.Select(“ServerGuid = ‘” + lstMonitorServers.Items[i].Value + “‘”);

                    if (existingRows.Length == 1) //found – row was in original server list
                    {
                        dtMonitorServersCurrent.Rows.Remove(existingRows[0]);
                    }

                    existingRows = dtMonitorservers.Select(“MonitorGuid = ‘” + lblMonitorID.Text.Substring(4) + “‘ and ServerGuid = ‘” + lstMonitorServers.Items[i].Value + “‘”);

                    if (existingRows.Length == 1) //found – row was in original server list
                    {
                        dtMonitorservers.Rows.Remove(existingRows[0]);
                    }
                }//if li.selected
            }//for
            SavetoSession(“CurrentMonitorServers”, dtMonitorServersCurrent);
            SavetoSession(“MonitorServersTable”, dtMonitorservers);
            lstMonitorServers.DataSource = dtMonitorServersCurrent.DefaultView;
            lstMonitorServers.DataTextField = “ServerName”;
            lstMonitorServers.DataValueField = “ServerGuid”;
            lstMonitorServers.DataBind();
            if (lstMonitorServers.Items.Count == 0) //is the list empty?
            {
                btnRemoveServer.Enabled = false;
            }
        }
        protected void Form_DataChanged(object sender, EventArgs e)
        {
            DataChanged = true;
            SavetoSession(“DataChanged”, DataChanged);
        }

#endregion
        private void LoadData()
        {
                string qsParms = string.Empty;
                XmlDocument xmlRules = new XmlDocument();

                qsParms = “?DC=” + ddlDC.SelectedValue + “&Account=” + txtAccount.Text;
                WebServiceCaller wc = new WebServiceCaller();
                wc.Exec(“http://&#8221; + Session["WebServicesServer"] + “/scom/SCOMAdmin.asmx/GetServiceStateMonitors” + qsParms);

                if (wc.Status == WebServiceCaller.WebServiceCallStatus.Succeeded)
                {
                    //build tables
                    BuildMonitorsTable();
                    XmlNode treeRoot = wc.Data;

                    if (treeRoot.HasChildNodes)
                    {
                        LoadMonitors(treeRoot); //load the data into a data table
                        tblMonitors.Visible = true;
                    }
                    else
                    {
                        lblErrMsg.Text = “No custom service state monitors found for account ” + txtAccount.Text;
                        tblMonitors.Visible = true;
                    }
                    LoadAllServers(); //load the list of servers in the account

                    SavetoSession(“dtMonitors”, dtMonitors);
                    SavetoSession(“MonitorServersTable”, dtMonitorservers);
                    SavetoSession(“CurrentMonitorServers”, dtMonitorServersCurrent);
                    SavetoSession(“OriginalMonitorServers”, dtMonitorserversOriginal);

                }//status=succeeded
                else //webservice failed
                {
                    lblErrMsg.Text = wc.StatusMessage;
                    tblMonitors.Visible = false;
                }
            
        }
        private void LoadMonitors(XmlNode root)
        {
            DataRow dr;
            XmlNode CurrNode;
            XmlNodeList nodeList;

            foreach (XmlNode n in root.ChildNodes)
            {
                dr = dtMonitors.NewRow();
                dr["MonitorGuid"] = n.Attributes["guid"].Value;

                CurrNode = n.SelectSingleNode(“./DisplayName”);
                dr["DisplayName"] = CurrNode.InnerText;

                CurrNode = n.SelectSingleNode(“./Criteria/ServiceName”);
                dr["ServiceName"] = CurrNode.InnerText;

                dtMonitors.Rows.Add(dr);

                nodeList = n.SelectNodes(“./Overrides/Override/Server[@enabled='true']“);
                foreach (XmlNode x in nodeList)
                {
                    dr = dtMonitorservers.NewRow();
                    dr["MonitorGuid"] = n.Attributes["guid"].Value;
                    dr["OverrideGuid"] = x.ParentNode.Attributes["id"].Value;
                    dr["ServerName"] = x.InnerText;
                    dr["ServerGuid"] = x.Attributes["id"].Value;
                    dtMonitorservers.Rows.Add(dr);
                }
            }//foreach monitor

            DataView dv = new DataView(dtMonitors);
            dv.Sort = “DisplayName”;
            lstMonitors.DataSource = dv;
            lstMonitors.DataTextField = “DisplayName”;
            lstMonitors.DataValueField = “MonitorGuid”;
            lstMonitors.DataBind();
        }
        private void LoadAllServers()
        {
            try
            {
            //get list of all servers in account that can be added to a monitor
                string qsParms = string.Empty;
                XmlDocument xmlServerList = new XmlDocument();
                qsParms = “?DC=” + ddlDC.SelectedValue + “&Account=” + txtAccount.Text + “&ServerFilter=”;

                WebServiceCaller wc = new WebServiceCaller();
                wc.Exec(“http://&#8221; + Session["WebServicesServer"] + “/scom/SCOMAgent.asmx/GetAgents” + qsParms);
                
                if (wc.Status == WebServiceCaller.WebServiceCallStatus.Succeeded)
                {
                    XmlNode treeRoot = wc.Data;
                    if (treeRoot.HasChildNodes)
                    {
                        //add servers/guids to arraylist so we can sort it
                        ArrayList al = new ArrayList();
                        foreach (XmlNode x in treeRoot.ChildNodes)
                        {
                            al.Add(new ListItem(x.InnerText,x.Attributes["guid"].Value));
                        }
                        al.Sort(new ListItemSorter());

                        //then bind it to the listbox
                        lstAllServers.Items.Clear();
                        lstAllServers.DataSource = al;
                        lstAllServers.DataTextField = “Text”;
                        lstAllServers.DataValueField = “Value”;
                        lstAllServers.DataBind();
                        lstAllServers.Enabled = true;
                        btnAddServer.Enabled = true;
                    }
                    else
                    {
                        lstAllServers.Items.Clear();
                        lstAllServers.Items.Add(“–None Found–“);
                        lstAllServers.Items.Add(“Check the Rackspace RegKey”);
                        lstAllServers.Items.Add(“HKLM\\Software\\Rackspace “);
                        lstAllServers.Items.Add(“and make sure that the “);
                        lstAllServers.Items.Add(“CustomerNumber is correct”);
                        lstAllServers.Items.Add(“on all devices running “);
                        lstAllServers.Items.Add(“the SCOM agent”);
                        lstAllServers.Enabled = false;
                        btnAddServer.Enabled = false;
                    }
                }//status=succeeded
                else //webservice failed
                {
                    lblErrMsg.Text = wc.StatusMessage;
                }
            }
            catch (Exception ex)
            {
                lblErrMsg.Text = EventLogWriter.GenericErrorMsg;
                EventLogWriter.LogEvent(ex);
            }
        }
       
        private void BuildMonitorsTable()
        {
            dtMonitors.Columns.Add(“MonitorGuid”);
            dtMonitors.Columns.Add(“ServiceName”);
            dtMonitors.Columns.Add(“DisplayName”);

            dtMonitorservers.Columns.Add(“MonitorGuid”);
            dtMonitorservers.Columns.Add(“OverrideGuid”);
            dtMonitorservers.Columns.Add(“ServerName”);
            dtMonitorservers.Columns.Add(“ServerGuid”);

            //dtMonitorserversCurrent holds servers that are applied/or to be applied to be to the current monitor
            dtMonitorServersCurrent = dtMonitorservers.Clone(); //duplicate the dtMonitorservers Table

            //dtMonitorserversOriginal hold the original list of servers applied to the current monitor, before any user changed
            //When committing, the Current and Original tables are compared to determine which servers need to be added/removed from the monitor via the WebService
            dtMonitorserversOriginal = dtMonitorservers.Clone(); //duplicate the dtMonitorservers table
            dtMonitorserversOriginal.Rows.Clear(); //and clear the data
        }//BuildMonitorsTable

        protected void InitDetailForm()
        {
            lblMonitorID.Text = string.Empty;
            txtDisplayName.Text = string.Empty;
            txtServiceName.Text = string.Empty;
            txtTicket.Text = string.Empty;

            lstMonitorServers.Items.Clear();
            lstAllServers.SelectedIndex = -1;

            //change the button text so we know that we are adding instead of updating
            btnCommit.Text = “Commit New Monitor”;

            //show the Commit and Reset buttons
            btnCommit.Visible = true;
            btnReset.Visible = true;

            // disable the remove servers button
            btnRemoveServer.Enabled = false;

            //display the table
            tblDetails.Visible = true;
        }

        private string AddUpdateMonitor(string CreateUpdate)
        {
            string qsParms = string.Empty;
            XmlDocument xmlRules = new XmlDocument();
            lblErrMsg.Text = string.Empty;

            qsParms = “?DC=” + ddlDC.SelectedValue;
            qsParms += “&Account=” + txtAccount.Text;
            if (CreateUpdate == “Update”)
                qsParms += “&MonitorGuid=” + lblMonitorID.Text.Substring(4); //chop off the ID: from the displayed monitorID
            
            qsParms += “&ServiceName=” + txtServiceName.Text;
            qsParms += “&ServiceDisplayName=” + txtDisplayName.Text;
            qsParms += “&Ticket=” + txtTicket.Text;
            qsParms += “&UserID=” + UserName;

            WebServiceCaller wc = new WebServiceCaller();
            string webMethod = CreateUpdate + “ServiceStateMonitor”; //webmethod name is either CreateServiceStateMonitor or UpdateServiceStateMonitor
            wc.Exec(“http://&#8221; + Session["WebServicesServer"] + “/scom/SCOMAdmin.asmx/” + webMethod + qsParms);

            if (wc.Status == WebServiceCaller.WebServiceCallStatus.Succeeded)
            {
                //add to datatable dtMonitors
                lblErrMsg.Text = “Custom Service monitor has been ” + CreateUpdate.ToLower() + “d for the \”” + txtDisplayName.Text +”\” service “; //Created or Updated msg
                XmlNode treeRoot = xmlRules.SelectSingleNode(“/Response/ReturnData”);
                lblMonitorID.Text = “ID: ” + treeRoot.FirstChild.InnerText; //show the new monitorid, if adding
                btnCommit.Text = “Commit Monitor Changes”;
                return treeRoot.FirstChild.InnerText;
            }//status=succeeded
            else //webservice failed
            {
                lblErrMsg.Text = wc.StatusMessage;
                return string.Empty;
            }
        }
        
        private void ApplyServersToMonitor(string MonitorGuid)
        {
            //compare lstOriginalMonitorServes to lstMonitorServers to see what was added/removed
            if (Session["CurrentMonitorServers"] != null)
                dtMonitorServersCurrent = (DataTable)Session["CurrentMonitorServers"];

            if (Session["OriginalMonitorServers"] != null)
                dtMonitorserversOriginal = (DataTable)Session["OriginalMonitorServers"];

            //newly added servers will have an empty Override Guid in the Current table
            DataRow[] newServers = dtMonitorServersCurrent.Select(“OverrideGuid = ””);
            foreach (DataRow r in newServers)
            {
                AddServerToMonitor(MonitorGuid, r["ServerGuid"].ToString());
            }
            
            //servers in Original but not current list need to be removed from monitor
            foreach (DataRow r in dtMonitorserversOriginal.Rows)
            {
                DataRow[] existingRow = dtMonitorServersCurrent.Select(“ServerGuid = ‘” + r["ServerGuid"].ToString() + “‘”);
                if (existingRow.Length == 0)
                {
                    RemoveServerFromMonitor(MonitorGuid, r["ServerGuid"].ToString());
                }
            }

        }
        private void AddServerToMonitor(string monitorGUID, string serverGUID)
        {
                string qsParms = string.Empty;
                XmlDocument xmlRules = new XmlDocument();
                //lblErrMsg.Text = string.Empty;

                qsParms = “?DC=” + ddlDC.SelectedValue;
                qsParms += “&MonitorGuid=” + monitorGUID;
                qsParms += “&ServerGuid=” + serverGUID;
                qsParms += “&Ticket=” + txtTicket.Text;
                qsParms += “&UserID=” + UserName;

                WebServiceCaller wc = new WebServiceCaller();
                wc.Exec(“http://&#8221; + Session["WebServicesServer"] + “/scom/SCOMAdmin.asmx/EnableMonitor” + qsParms);

                if (wc.Status == WebServiceCaller.WebServiceCallStatus.Succeeded)
                {
                    if (!DataChanged)
                        lblErrMsg.Text = “Server list has been updated”;

                }//status=succeeded
                else //webservice failed
                {
                    lblErrMsg.Text = wc.StatusMessage;
                }
        }
        private void RemoveServerFromMonitor(string monitorGUID, string serverGUID)
        {
            string qsParms = string.Empty;
            XmlDocument xmlRules = new XmlDocument();
            lblErrMsg.Text = string.Empty;

            qsParms = “?DC=” + ddlDC.SelectedValue;
            qsParms += “&MonitorGuid=” + monitorGUID;
            qsParms += “&ServerGuid=” + serverGUID;
            qsParms += “&Ticket=” + txtTicket.Text;
            qsParms += “&UserID=” + UserName;

            WebServiceCaller wc = new WebServiceCaller();
            wc.Exec(“http://&#8221; + Session["WebServicesServer"] + “/scom/SCOMAdmin.asmx/DisableMonitor” + qsParms);

            if (wc.Status == WebServiceCaller.WebServiceCallStatus.Succeeded)
            {
                if (!DataChanged)
                    lblErrMsg.Text = “Server list has been updated”;
            }//status=succeeded
            else //webservice failed
            {
                lblErrMsg.Text = wc.StatusMessage;
                //tblMonitors.Visible = false;
            }
        }
        
        private bool ValidData()
        {
            bool status = true;
            
            if (txtServiceName.Text == string.Empty)
            {
                lblErrMsg.Text += “Service Name is required<br />”;
                txtServiceName.Focus();
                status = false;
            }
            else
            {
                if (HasSpecialChars(txtServiceName.Text))
                {
                    lblErrMsg.Text += “Service Name contains invalid characters. Valid characters are a-z, 0-9, space, hyphen and underscore<br />”;
                    txtServiceName.Focus();
                    status = false;
                }
            }

            if (txtDisplayName.Text == string.Empty)
            {
                lblErrMsg.Text += “Display Name is required<br />”;
                txtDisplayName.Focus();
                status = false;
            }
            else
            {
                if (HasSpecialChars(txtDisplayName.Text))
                {
                    lblErrMsg.Text += “Display Name contains invalid characters. Valid characters are a-z, 0-9, space, hyphen and underscore<br />”;
                    txtDisplayName.Focus();
                    status = false;
                }
            }

            if (txtTicket.Text == string.Empty)
            {
                lblErrMsg.Text += “Ticket ID is required<br />”;
                txtTicket.Focus();
                status = false;
            }
            else
            {
                if (HasSpecialChars(txtTicket.Text))
                {
                    lblErrMsg.Text += “Display Name contains invalid characters. Valid characters are a-z, 0-9, space, hyphen and underscore<br />”;
                    txtTicket.Focus();
                    status = false;
                }
            }
            return status;
        }

        private bool HasSpecialChars(string s)
        {
            Regex pattern = new Regex(@”^[A-Za-z0-9_ \-]+$”, RegexOptions.IgnoreCase);
            return !pattern.IsMatch(s);
        }
        
        private void SavetoSession(string sVar, object obj)
        {
            if (Session[sVar] == null)
            { Session.Add(sVar, obj); }
            else { Session[sVar] = obj; }
        }

private void AddToARIC()
        {
            string qsParms = string.Empty;
            XmlDocument xmlRules = new XmlDocument();
            lblErrMsg.Text = string.Empty;

            qsParms = “?ARICSourceID=1″;
            qsParms += “&Account=” + txtAccount.Text;

            qsParms += “&AlertText=” + txtAccount.Text + ” – ” + txtDisplayName.Text + ” service is not running”;

            WebServiceCaller wc = new WebServiceCaller();
            wc.Exec(“http://&#8221; + Session["WebServicesServer"] + “/scom/SCOMAdmin.asmx/AddToARIC” + qsParms);

            if (wc.Status != WebServiceCaller.WebServiceCallStatus.Succeeded) //webservice call failed
            {
                lblErrMsg.Text = wc.StatusMessage;
            }

        }

        private void UpdateARIC()
        {
            string qsParms = string.Empty;
            XmlDocument xmlRules = new XmlDocument();
            lblErrMsg.Text = string.Empty;

            qsParms = “?ARICSourceID=1″;
            qsParms += “&Account=” + txtAccount.Text;
            qsParms += “&OldAlertText=” + txtAccount.Text + ” – ” + lstMonitors.SelectedItem.Text + ” service is not running”;
            qsParms += “&NewAlertText=” + txtAccount.Text + ” – ” + txtDisplayName.Text + ” service is not running”;

            WebServiceCaller wc = new WebServiceCaller();
            wc.Exec(“http://&#8221; + Session["WebServicesServer"] + “/scom/SCOMAdmin.asmx/UpdateARIC” + qsParms);

            if (wc.Status != WebServiceCaller.WebServiceCallStatus.Succeeded ) //webservice call failed
            {
                lblErrMsg.Text = wc.StatusMessage;
            }
        }
    }//class
}//namespace

Follow

Get every new post delivered to your Inbox.