Welcome to another System Center PFE blog post. In this publication I will continue to highlight how the System Center Suite of products can help manage and automate complex processes. If you’ve read my first post in this series, you will recall that the process being detailed is the graceful application of updates to a multi-node SQL cluster. I will continue to use this scenario as the subject process for this blog; however, make no mistake, this series of posts is not about updating SQL clusters, but rather an introduction to the features of System Center and process automation. The goal of this article series is to show the potential of ‘IT as a Service’ while using complex real world use cases as the example subject matter.

 

Goals for this blog:

  • Quick discussion about Orchestrator Interfaces.
  • Demonstrate the creation and use of a C#/ASP.NET External Interface that will pass Initialization data to our SQL Cluster Updating Runbook and start the Runbook.

 

Scenario / Use Case:

As a member of the Contoso IT staff managing System Center and Automation, you have completed development on a series of cluster updating Orchestrator Runbooks, which have successfully automated the cluster updating process. While the native System Center Orchestrator 2012 Orchestration Console provides the necessary interfaces from which to pass initialization data and start the updating process, management has asked for a custom interface that can be integrated into the already existing Contoso IT portal. Your task is to develop a custom System Center Orchestrator web interface which will interact with the Orchestrator Web Service allowing Contoso staff to pass initialization data and start the Cluster Updating process.

 

Interfaces:

When speaking of interfaces, we are referring to any programmatic method by which to interact with the Orchestrator Web Service or Runbook Server. Through these interfaces we can pass initialization data to our Runbooks, start and stop a Runbook, and retrieve data about Runbooks.

Native Interfaces - Out of the box we have the Runbook Designer, Runbook Tester, and the Orchestration Console. Each of these has a target use case, with the Orchestration console being most suitable as a ‘published interface’. In my last blog post I demonstrated use of the Orchestration Console. While the Orchestration Console can perform all interface requirements, it may not suit all situations, such as the scenario detailed in this publication. What are the alternatives?

Orchestrator Web Service – Orchestrator will ship with a REST-based web service providing a surface from which to interface with Orchestrator Runbooks. Basically we can interface with Orchestrator using any programmatic method that is capable of interacting with a REST-based web service (PowerShell, .NET, VBSCRIPT, Etc.). This is the interfacing method we will be examining in this article.

System Center Service Manager 2012 – while Service Manage will also use the Orchestrator Web Service as the interface mechanism, Orchestrator and Service Manager are so tightly integrated and powerful when coupled that I’ve decided Service Manager is worthy of a bullet point in its own right. In my opinion this is the true nirvana of Orchestrator Interfaces. Stay tuned, I will be examining the marriage of System Center Service Manager 2012 and System Center Orchestrator 2012 in future article posting.

 

Creating the custom interface:

With an understanding of what an interface is, let’s explore the creation of our own. Before getting started, here are a few resources I used as reference material when developing this solution.

Robert Hearn - Fun with the Orchestrator Beta Web Service and Powershell

Damian Flynn - Orchestrator, C#, and Runbooks

Assumptions - The assumption here is that we have an Orchestrator Runbook solution tested, in place, and ready for consumption.  Additionally we need to verify that the Orchestrator Web Service is functioning. To do so browse to HTTP://<SERVERNAME>:81/Orchestrator2012/Orchestrator.svc - this should produce a page containing XML. If it does you should be ready to start the exercise.

Step 1:  Custom Class File -Before starting our project in Visual Studio, we need to generate a custom class file containing the client data service classes that our .NET application can utilize to access the web service. This is quite easy. Open up a command prompt (I’ve done this on the Orchestrator box but I do not believe this is necessary), navigate to the following folder ‘%windir%\Microsoft.NET\Framework\v3.5’, and run the following command

DataSvcUtil.exe /dataservicecollection /version:2.0 /language:CSharp /out:desiredfilename.cs /uri: HTTP://<SERVERNAME>:81/Orchestrator2012/Orchestrator.svc

The output will look similar to the following and the .CS file can be found in the folder from which DataSvcUtil.exe was executed.


More information on how to use DataSvcUtil.exe can be found here - http://msdn.microsoft.com/en-us/library/ee383989.aspx

 Step 2:  Design Our Web Application – For the sake of this demonstration this application will be very simple. A few text boxes and a submit button. I will not go into the details of creating this form.

 

Step 3: Setting up the .NET Environment - Once the form design has been completed, we will need to set up the .NET environment. From within the Visual Studio designer, double click on the ‘Update’ button in order to bring up the code editor with focus on the Default.aspx.cs file (if this file has not been renamed).

  • Add using System.Xml.Ling; to the using statements.
  • Add the .CS File created in step 1 to the project – right click on the project in solution explorer, add existing item, select the .CS file.
  • Add a reference right click on References, Add Reference, select .NET, and select System.Data.Services.Client.

When finished you will see the following three items boxed in red.

 

 Step 4: Begin Coding – For the sake of this blog post size, I will just paste the code here and give a quick description of the relevant lines.

 

Code Snippet
  1. protected void Button1_Click(object sender, EventArgs e)
  2.       {
  3.  
  4.          string strServer = txtServer.Text;
  5.          string strEmail = txtEmail.Text;
  6.          string strCluster;
  7.  
  8.          if (chkCluster.Checked)
  9.             strCluster = "True";
  10.          else
  11.             strCluster = "False";
  12.                         
  13.          var scorchSVC = new Microsoft.SystemCenter.Orchestrator.WebService.OrchestratorContext(new Uri(@"http://twosys2012scorc:81/orchestrator2012/orchestrator.svc"));
  14.          scorchSVC.Credentials = new System.Net.NetworkCredential("username", "password", "domain");
  15.  
  16.          var runbooks = (from rbData in scorchSVC.Runbooks
  17.                          where rbData.Name == "1.0 - Cluster Updates"
  18.                          select rbData).ToList();
  19.  
  20.          var runbookpars = (from rbData in scorchSVC.RunbookParameters
  21.                             where rbData.RunbookId == runbooks.Single().Id
  22.                             select rbData).ToList();
  23.  
  24.          var input1param = (from rbData in runbookpars
  25.                             where rbData.Name == "Server"
  26.                             select rbData).Single();
  27.  
  28.          var input2param = (from rbData in runbookpars
  29.                             where rbData.Name == "Email"
  30.                             select rbData).Single();
  31.  
  32.          var input3param = (from rbData in runbookpars
  33.                             where rbData.Name == "Cluster"
  34.                             select rbData).Single();
  35.  
  36.          var paramxml = new XDocument(
  37.                         new XElement("Data",
  38.                            new XElement("Parameter",
  39.                               new XElement("Name", input1param.Name),
  40.                               new XElement("ID", input1param.Id.ToString("B")),
  41.                               new XElement("Value", strServer)
  42.                                     ),
  43.                             new XElement("Parameter",
  44.                               new XElement("Name", input2param.Name),
  45.                               new XElement("ID", input2param.Id.ToString("B")),
  46.                               new XElement("Value", strEmail)
  47.                                     ),
  48.                             new XElement("Parameter",
  49.                               new XElement("Name", input3param.Name),
  50.                               new XElement("ID", input3param.Id.ToString("B")),
  51.                               new XElement("Value", strCluster)
  52.                                     )));
  53.  
  54.          var job = Microsoft.SystemCenter.Orchestrator.WebService.Job.CreateJob(System.Guid.NewGuid(), runbooks.Single().Id, "user1", DateTime.Now, "user1", DateTime.Now);
  55.  
  56.          string strParam = paramxml.Document.ToString();
  57.  
  58.          job.Parameters = strParam;
  59.          scorchSVC.AddToJobs(job);
  60.          scorchSVC.SaveChanges();
  61.                  
  62.       }

Line 35: Creating a new Object or Class Instance of the class created in step 1.

Line 36: Credentials.

Line 38: Retrieve our Runbook data where rbData.Name = the name of the first runbook in the SQL Cluster update series.

Line 42: Retrieve our Runbook parameters.

Line 46: Prepare the data for input parameter 1 (Server or Cluster Name).

Line 50: Prepare the data for input parameter 2 (Indication that we are updating a cluster).

Line 46: Prepare the data for input parameter 3 (email address).

Line 58: Prepare our XML which will be passed to the Orchestrator Web Service.

Line 78: Place the XML into a string for ‘transport’.

Line 80: Add parameters and commit job to Orchestrator Web Service.

That is it. We now have our own custom GIU interface from which to start this particular set up Runbooks. This code can be translated into any C# application for reuse.

 

Video Demonstration:

Let’s take a look at the process in action.