System Center 2012 SP1 – Orchestrator: Automate Runbooks with PowerShell

In our tour of System Center 2012 SP1 – Orchestrator we have introduced the primary Runbook Designer activity types, those being actions or monitors. As we continue to embrace the functions offered by Orchestrator, the time will come when we will desire even more options. This is specifically the point when the Orchestrator Web Service finally comes into play, acting as the gateway to true extensibility.

System Center 2012 SP1 – Orchestrator: Scenarios

If you have not yet found yourself wondering if a certain runbook could be automatically started as soon as other jobs are completed, then you have not yet fully embraced the potential of this wonderful utility.

Consider this example: You run a daily backup process after which you execute a few checks so that you have confidence the backup worked successfully. Now, consider the possibility of running these checks and balances as a runbook in System Center 2012 SP1 – Orchestrator. In Orchestrator, you can check WMI, Event Logs, Run Database queries, and more – great, right? But there’s a problem: How do I tell Orchestrator to run this check for me automatically?

The obvious option might be to set a scheduled time for the runbook to execute, but what would happen if the backup paused due to a tape change? Now the runbook may start too early and fail the checks. You could use a Monitor activity for the backup software, if we had one, but perhaps you don’t. Hmmm, this might be a blocking issue after all.

PowerShell to the Rescue

What we really need is the ability to start the runbook by some other method, which coincidentally is precisely why we will utilize the Web Service. Using a simple PowerShell command script we can actually create a HTTP connection to service and start the runbook.

​ # Indicate the location of the Web Service, the credentials required to authenticate using, and the Runbook GUID 
$myCredentials = Get-Credential("Domain\Username")
$mySCOWebService = "http://pdc-sc-or01.diginerve.net:81/Orchestrator2012/Orchestrator.svc/Jobs/"
$xmlQuery = '<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
<content type="application/xml">
<m:properties>
<d:RunbookId type="Edm.Guid">RunbookGUID</d:RunbookId>
</m:properties>
</content>
</entry>
'

#Using the .NET Framework, create a new HTTP $httpSession object

$httpSession = [System.Net.HttpWebRequest]::Create($mySCOWebService)
$httpSession.Credentials = $myCredentials
$httpSession.Accept = "application/atom+xml,application/xml"
$httpSession.Headers.Add("Accept-Charset", "UTF-8")
$httpSession.ContentType = "application/atom+xml"
$httpSession.Method = "POST"
$httpConnection=new-object System.IO.StreamWriter $httpSession.GetRequestStream()

# Place our Query in the request session we have established and send it to Orchestrator

$httpConnection.Write($xmlQuery)
$httpConnection.Flush()
$httpConnection.Close()

# Now, check the response we received from Orchestrator, to ensure that the request was successful

$httpSessionResponse=$httpSession.GetResponse()
$httpResponse=$httpSessionResponse.GetResponseStream()
$xmlResponse=new-object System.IO.StreamReader $httpResponse
$results=$xmlResponse.ReadToEnd()
$xmlResponce.Close()
$httpSessionResponse.Close()

Examining this script, we can quickly see that the process is broken into four main components.

  • In the first section, we simply replace the domain credentials, Web Service URL, and the Runbook GUID, each highlighted in bold italics with the correct values for our environment.
  • Once these customization are complete, we will create a .NET framework reference to the HTTP subsystem to create a HTTP Session object, setting it up with our credentials, HTTP type, and HTTP formats.
  • Once we have the session object defined, we then place our XML query, which indicated the GUID of the runbook we wish to start, as the payload for the HTTP post.
  • Finally, we can then check what happened, taking the results of our post, and formatting the outback, which is stored in the object $Result in its default XML structure.

(Note: If you wish to see this in C#, you can search my blog for a detailed example, including the options required in the XML query if you require to pass parameters to the runbook.)

Leveraging this newfound ability we can reconsider our backup check challenge and address the original timer issue by using the above sample to create a simple script that will launch our runbook for us. The only real change required would be to include our password in the credential, instead of the default interactive prompt. Then in the properties of the backup job, we normally have the ability to execute a post-job script, which is the perfect place for us to solve our dilemma.

Using this trick, the boundaries to what you can actually automate are reduced and your job can take many steps to getting easier.