Web service SCSM permettant de gérer les incidents (création / visualisation)
SCSM 2010 (System Center Service Manager) permet principalement la gestion des incidents, changements, problèmes, activités. La création d’un ticket peut se faire :
- Via la console.
- Via l’envoi d’un mail.
- Via un portail Web.
La tentation était trop grande de créer un web service en se basant sur le SDK SCSM permettant de créer et visualiser ces incidents. Un Web Service pouvant être consommé facilement, il est donc possible d’envisager les scénarios suivants :
- Création d’un gadget : l’utilisateur pourra dès son poste de travail gérer ces incidents (les créer et visualiser leur statut).
- Insertion dans des applications Web d’un lien permettant de consommer le Web Service afin de directement créer un incident. Par exemple, l’url pourra être mis dans le champ commentaire…
Le Web service décrit ci-dessous est composé de deux web méthodes :
- Web méthode 1 : Permettre à l’utilisateur de créer un incident. L’incident créé pré-rempli les champs obligatoire.
- Web méthode 2 : Lister tous les incidents liés à l’utilisateur.
//WEB METHOD PERMETTANT DE CREER UN INCIDENT - CreateIncident
[WebMethod]
public string CreateIncident(string username, string Title, string Desc)
{
//if username null
if (username != "")
{
//if textboxTitle is not null, create incident (adding file is optional)
if (Title != "")
{
//if textboxDesc is not null, create incident (adding file is optional)
if (Desc != "")
{
//First, create a connection to the management group. Replace 'localhost' with your server name if you want to run remotely.
EnterpriseManagementGroup mg = new EnterpriseManagementGroup(ServerName);
//Next, you'll need the version and keytoken of the system management packs. This is an easy way to do it.
ManagementPack mpSystem = mg.ManagementPacks.GetManagementPack(SystemManagementPack.System);
Version version = mpSystem.Version;
string keytoken = mpSystem.KeyToken;
//Next, get the incident library management pack by ID - System.WorkItem.Incident.Library
ManagementPack mpIncidentLibrary = mg.GetManagementPack("System.WorkItem.Incident.Library", keytoken, version);
//Next, get the incident library management pack by ID - System.WorkItem.Library
ManagementPack workItemMp = mg.GetManagementPack("System.WorkItem.Library", keytoken, version);
// Next, get the incident class.
ManagementPackClass classIncident = mg.EntityTypes.GetClass("System.WorkItem.Incident", mpIncidentLibrary);
// Next, create a new object projection.
EnterpriseManagementObjectProjection projectionIncident = new EnterpriseManagementObjectProjection(mg, classIncident);
// Next, set the Title property on the incident.
projectionIncident.Object[classIncident, "Title"].Value = Title;
// Next, set the Desc property on the incident.ext
projectionIncident.Object[classIncident, "Description"].Value = Desc;
// Next, set the ID property on the incident.
projectionIncident.Object[classIncident, "Id"].Value = "IR-{0}";
// Next, set the status property on the incident.
ManagementPack statusMp = projectionIncident.Object[classIncident, "Status"].Type.GetManagementPack();
ManagementPackEnumeration activeStatusEnum = statusMp.GetEnumerations().GetItem(IncidentStat);
projectionIncident.Object[classIncident, "Status"].Value = activeStatusEnum.Id;
// Next, set the Classification property on the incident.
ManagementPack incidentConfigurationMp = mg.ManagementPacks.GetManagementPack("ServiceManager.IncidentManagement.Configuration", null, version);
ManagementPackEnumeration ProblemEnum = incidentConfigurationMp.GetEnumerations().GetItem(IncidentClassification);
projectionIncident.Object[classIncident, "Classification"].Value = ProblemEnum.Id;
// Next, set the Source property on the incident.
ManagementPack SourceMp = projectionIncident.Object[classIncident, "Source"].Type.GetManagementPack();
ManagementPackEnumeration SourceEnum = SourceMp.GetEnumerations().GetItem(IncidentSrc);
projectionIncident.Object[classIncident, "Source"].Value = SourceEnum.Id;
//Next, set the affected user on the incident.
//string usernameaffected = System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString();
string AffectUser = username.Split('@')[0].ToString();
string AffectDomain = username.Split('@')[1].ToString();
ManagementPack mpWindows = mg.ManagementPacks.GetManagementPack(SystemManagementPack.Windows);
ManagementPackClass userClass = mg.EntityTypes.GetClass("Microsoft.AD.User", mpWindows);
EnterpriseManagementObject user = null;
//Create the criteria XML and criteria object
//string userCriteria = CreateUserCriteriaXml(mg, "user2");
// This is XML that validates against the Microsoft.EnterpriseManagement.Core.Criteria schema.
string userCriteria = String.Format(@"
<Criteria xmlns=""https://Microsoft.EnterpriseManagement.Core.Criteria/"">
<Expression>
<SimpleExpression>
<ValueExpressionLeft>
<Property>$Target/Property[Type='Microsoft.AD.User']/UPN$</Property>
</ValueExpressionLeft>
<Operator>Equal</Operator>
<ValueExpressionRight>
<Value>{2}@{3}</Value>
</ValueExpressionRight>
</SimpleExpression>
</Expression>
</Criteria>
", mpWindows.KeyToken, mpWindows.Version.ToString(), AffectUser, AffectDomain);
EnterpriseManagementObjectCriteria criteria = new EnterpriseManagementObjectCriteria(userCriteria, userClass, mpWindows, mg);
//Retrieve the user that corresponds to the criteria
IEnumerable<EnterpriseManagementObject> users =
(IEnumerable<EnterpriseManagementObject>)mg.EntityObjects.GetObjectReader<EnterpriseManagementObject>(criteria, ObjectQueryOptions.Default);
//Get the enumerator
IEnumerator<EnterpriseManagementObject> enumUsers = users.GetEnumerator();
while (enumUsers.MoveNext())
{
user = enumUsers.Current;
break;
}
if (user == null)
{
//textBlock1.Text = "Contact helpdesk (user issue)!"
return UserError;
}
else
{
ManagementPackRelationship createdfor = mg.EntityTypes.GetRelationshipClass("System.WorkItemAffectedUser", workItemMp);
projectionIncident.Add(user, createdfor.Target);
}
ManagementPack mpIncidentUrgencyEnum = projectionIncident.Object[classIncident, "Urgency"].Type.GetManagementPack();
ManagementPackEnumeration enumUrgency = mpIncidentUrgencyEnum.GetEnumeration(IncidentUrgency);
projectionIncident.Object[classIncident, "Urgency"].Value = enumUrgency.Id;
ManagementPack mpIncidentImpactEnum = projectionIncident.Object[classIncident, "Urgency"].Type.GetManagementPack();
ManagementPackEnumeration enumImpact = mpIncidentUrgencyEnum.GetEnumeration(IncidentImpact);
projectionIncident.Object[classIncident, "Impact"].Value = enumImpact.Id;
projectionIncident.Commit();
return OutpoutCreate;
}
//if Desc is null
else
{
//"Desc. field error!";
return FieldErrorDesc;
}
}
//if Title is null
else
{
//"Title field error!";
return FieldErrorTitle;
}
}
else
{
//User error
return UserError;
}
}
//WEB METHOD PERMETTANT DE LISTER TOUS CES INCIDENTQ - ListAllIncidents
[WebMethod]
public string ListAllIncidents(string username)
{
if (username != "")
{
EnterpriseManagementGroup mg = new EnterpriseManagementGroup(ServerName);
// References to management packs that contain classes used in this example.
ManagementPack systemMp = mg.ManagementPacks.GetManagementPack(SystemManagementPack.System);
ManagementPack incidentMp = mg.ManagementPacks.GetManagementPack("ServiceManager.IncidentManagement.Library",
systemMp.KeyToken, systemMp.Version);
ManagementPack workitemMp = mg.ManagementPacks.GetManagementPack("System.WorkItem.Library",
systemMp.KeyToken, systemMp.Version);
//Next, set the affected user on the incident.
//string usernameaffected = System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString();
string AffectUser = username.Split('@')[0].ToString();
string AffectDomain = username.Split('@')[1].ToString();
ManagementPack mpWindows = mg.ManagementPacks.GetManagementPack(SystemManagementPack.Windows);
ManagementPackClass userClass = mg.EntityTypes.GetClass("Microsoft.AD.User", mpWindows);
// This is XML that validates against the Microsoft.EnterpriseManagement.Core.Criteria schema.
string userCriteria = String.Format(@"
<Criteria xmlns=""https://Microsoft.EnterpriseManagement.Core.Criteria/"">
<Expression>
<SimpleExpression>
<ValueExpressionLeft>
<Property>$Target/Property[Type='Microsoft.AD.User']/UPN$</Property>
</ValueExpressionLeft>
<Operator>Equal</Operator>
<ValueExpressionRight>
<Value>{2}@{3}</Value>
</ValueExpressionRight>
</SimpleExpression>
</Expression>
</Criteria>
", mpWindows.KeyToken, mpWindows.Version.ToString(), AffectUser, AffectDomain);
EnterpriseManagementObject userAff = null;
EnterpriseManagementObjectCriteria criteria = new EnterpriseManagementObjectCriteria(userCriteria, userClass, mpWindows, mg);
//Retrieve the user that corresponds to the criteria
IEnumerable<EnterpriseManagementObject> users =
(IEnumerable<EnterpriseManagementObject>)mg.EntityObjects.GetObjectReader<EnterpriseManagementObject>(criteria, ObjectQueryOptions.Default);
//Get the enumerator
IEnumerator<EnterpriseManagementObject> enumUsers = users.GetEnumerator();
while (enumUsers.MoveNext())
{
userAff = enumUsers.Current;
break;
}
if (userAff == null)
{
//"your account has an issue and can't create a incident. Please contact your administrator"
return UserError;
}
else
{
// Define the type projection that you want to query for.
ManagementPackTypeProjection incidentTypeProjection = mg.EntityTypes.GetTypeProjection(
"System.WorkItem.Incident.ProjectionType", incidentMp);
// Define the query criteria string.
string incidentCriteria = String.Format(@"
<Criteria xmlns=""https://Microsoft.EnterpriseManagement.Core.Criteria/"">
<Reference Id=""System.WorkItem.Library"" PublicKeyToken=""{0}"" Version=""{1}"" Alias=""WorkItem"" />
<Reference Id=""Microsoft.Windows.Library"" PublicKeyToken=""{0}"" Version=""{1}"" Alias=""Windows"" />
<Expression>
<SimpleExpression>
<ValueExpressionLeft>
<Property>$Target/Path[Relationship='WorkItem!System.WorkItemAffectedUser' SeedRole='Source' TypeConstraint='Windows!Microsoft.AD.User']/Property[Type='Windows!Microsoft.AD.User']/UPN$</Property>
</ValueExpressionLeft>
<Operator>Like</Operator>
<ValueExpressionRight>
<Value>{2}@{3}</Value>
</ValueExpressionRight>
</SimpleExpression>
</Expression>
</Criteria>
", systemMp.KeyToken, systemMp.Version.ToString(), AffectUser, AffectDomain);
// Define the criteria object by using one of the criteria strings.
ObjectProjectionCriteria criteria1 = new ObjectProjectionCriteria(incidentCriteria, incidentTypeProjection, mg);
//Création de l'entête du XML
StringBuilder sb = new StringBuilder();
sb.AppendLine("<IncidentsList>");
// For each retrieved type projection, display the properties.
foreach (EnterpriseManagementObjectProjection projection in
mg.EntityObjects.GetObjectProjectionReader<EnterpriseManagementObject>(criteria1, ObjectQueryOptions.Default))
{
string IncStatus = projection.Object[null, "Status"].Value.ToString();
//string incDesc = projection.Object[null, "Description"].Value.ToString();
string IncID = projection.Object[null, "Id"].Value.ToString();
string IncTitle = projection.Object[null, "Title"].Value.ToString();
sb.AppendFormat("<Incident>{0}</Incident>" + Environment.NewLine, "TEST");
switch (IncStatus)
{
case "IncidentStatusEnum.Active":
//" - Active";
sb.AppendFormat("<Incident>{0}</Incident>" + Environment.NewLine, IncID + " || " + IncTitle + " || " + "Active");
break;
case "IncidentStatusEnum.Resolved":
//" - Resolved";
sb.AppendFormat("<Incident>{0}</Incident>" + Environment.NewLine, IncID + " || " + IncTitle + " || " + "Resolved");
break;
case "IncidentStatusEnum.Closed":
//" - Closed";
sb.AppendFormat("<Incident>{0}</Incident>" + Environment.NewLine, IncID + " || " + IncTitle + " || " + "Closed");
break;
case "IncidentStatusEnum.Active.Pending":
//" - Pending";
sb.AppendFormat("<Incident>{0}</Incident>" + Environment.NewLine, IncID + " || " + IncTitle + " || " + "Pending");
break;
}
}
//Fermture du XML
sb.AppendLine("</IncidentsList>");
string ListIncidentsFinal = sb.ToString();
//"your account has an issue and can't create a incident. Please contact your administrator"
return sb.ToString();
}
}
else
{
//"Username field error!"
return UserError;
}
}
Encore une fois, Cet exemple sert de base et doit être modifié, adapté en fonction des besoins ! Il est là pour vous faire voire que c’est possible facilement. Vos retours sont les bienvenus.
Comments
Anonymous
January 01, 2003
Bonjour Mathieu, Pour répondre à ta question, un web service fera très bien l’affaire dans ton cas car il te permettra de créer un incident en remplissant les champs disponibles. Dans l’exemple je ne rempli que les champs : affecteduser, title, desc, impact, urgency de l’incident mais rien ne t’empêche d’en remplir d’autres. De plus, si tu veux remplir des informations qui ne sont pas présentes dans l’incident tu peux toujours créer ton propre modèle d’incident en définissant tes champs. Côté Web service il n’y a pas de limite à ma connaissance. Tu peux passer autant de paramètres que tu le souhaites avec les types que tu veux : int, string, double… JulienAnonymous
March 03, 2011
Bonjour Julien, Merci pour cet exemple ^^ Actuellement nous avons une brique de gestion des exceptions dans chacune de nos applications métier. Nous utilisons Service Manager pour notre gestion des incidents depuis peu de temps et nous avons pour projet de connecter notre brique avec Service Manager en utilisant les web services. Cependant, nous avons besoin de remonter plusieurs informations en provenance des applications et nous nous demandons s'il est possible de créer des web services custom pour créer des incidents et quelles sont les limites de cette méthode (nombre de paramètres que l'on peut passer à notre web Service, les types d'objet etc...) Est-ce que vous avez des informations complémentaires à ce sujet ? Nous pouvez me répondre à mon adresse : math.francesch@gmail.com Merci. MathieuAnonymous
March 07, 2011
Bonjour Julien, Je te remercie pour ton retour. Nous allons monter en interne un serveur de test afin de réaliser nos tests d'échanges de données entre nos tierces applications et le web service "Création d'un incident" de SCSM. Cdlt, Mathieu