With Service Management Automation (SMA), the new capability in Windows Azure Pack and Orchestrator 2012 R2, creating and running runbooks are core tasks for IT professionals who are automating repetitive and complex tasks and integrating across systems. SMA uses the PowerShell workflow engine to run runbooks, which means that runbooks are created as PowerShell workflows (see the Runbook Concepts article for an introduction).
As you create SMA runbooks, you will want to be aware of and follow best practices in order to get the most out of the system. Creating runbooks involves an understanding of PowerShell, PowerShell Workflow, and SMA. At the end of the day, if you are familiar with PowerShell, then creating SMA runbooks is straightforward.
In this post, I will cover a few of the basic concepts that will help you create high-quality runbooks. Other posts in this series will cover other useful aspects of runbook creation and management. The concepts covered in this post are the following:
Defining Input Parameters
Most runbooks require some input data to be provided before execution. Thus, it is common during runbook authoring to define the input parameters that will be needed. The main attributes that define an input parameter are these:
SMA supports these attributes of input parameters for runbooks. PowerShell supports many more attributes of input parameters such as validation, aliases, and parameter sets; however SMA currently supports only the list above.
The screenshot below shows parameters defined in a runbook. (For more illustration you can also look at the Sample-Using-RunbookParameters runbook that is pre-installed with SMA.)
Using this example, to add a user who works for the company Contoso and has admin rights you would submit these PowerShell commands:
In some cases, the [switch] parameter type can be useful in SMA runbooks; however, there are some cases where it is simpler to use the [boolean] type. The reasons for using one or the other are explained in this blog post.
In PowerShell Workflow when you call an activity or another workflow (runbook) all parameters must be referenced by name and not position. This restriction does not apply to cmdlets which allow positional parameters.
Best Practice: As a best practice, you should be very explicit when declaring input parameters to your SMA runbooks. Take the example above as a guide and always include the parameter Type, Name, and whether it is Mandatory or not. Note that if you set a default value for a parameter, then it will be an optional parameter regardless of how you set the Mandatory attribute. If you leave out the Mandatory attribute then by default the parameter is optional; however, it is always best to explicitly declare this. When you name a parameter use letters, numbers, and underscore characters (don’t use the hyphen character because parameter names with hyphens need special handling that you want to avoid).
If you want to be able to start your runbooks from the SMA portal using the Start Runbook wizard UI then keep these things in mind about input parameters:
If you want to start a runbook from within a runbook using the Start-SmaRunbook cmdlet (more about this cmdlet later in this post) then keep these things in mind about input parameters (and see the code example below):
Defining Output Type
PowerShell has long supported the definition of output type in functions and cmdlets with the use of the OutputType attribute. This attribute has no effect during runtime, and instead has been provided as a way for tools to learn, at design time, the object types that cmdlets output without having to run them.
OutputType can be used in PowerShell workflow, and you should include OutputType in runbooks that have output. Place the OutputType attribute near the top of the runbook, just before any parameter declarations. Here is an example of the use of OutputType in a runbook.
As SMA evolves, and the toolset for creating runbooks is expanded and enhanced, it will be important that cmdlets and runbooks include the OutputType definition and then adhere to that contract.
Best Practice: This is an easy best practice to follow: always include OutputType in your cmdlets and runbooks that have output.
Calling Other Runbooks from a Runbook
One of the best practices when creating code of any kind is modularization: creating discrete, reusable code units. For SMA this means putting self-contained tasks within cmdlets and runbooks, and then re-using those in many runbooks. Thus, it could be common practice for a parent runbook to call one or more child runbooks as part of the process being executed.
There are two ways to call child runbooks in SMA:
As a side note, we use the general terms “nested” or "child" for any child runbook that is called from a parent runbook. PowerShell uses the verb “invoke” for operations that are initiated and run synchronously and the verb “start” for operations that are initiated and run asynchronously; we will follow this precedent and use the verbs “invoke” and “start” for synchronous and asynchronous child runbooks, respectively.
Invoke a Runbook Inline
Runbooks that are invoked inline run in the same job as the parent runbook. This means that the parent workflow will wait for a child runbook to finish (synchronous) before continuing with the next part of the process. This also means that all exceptions thrown by the child runbook and all stream output produced by the child runbook are going to be associated with the parent job; therefore all tracking of child runbook execution and output will be through the job associated with the parent runbook.
When you start a runbook that has child runbooks invoked inline, the child runbooks (and all descendants) get compiled into the parent runbook before execution starts. During this compilation phase the parent runbook is parsed for the names of child runbooks; this parsing happens recursively through all descendant runbooks. When the complete list of runbooks is obtained the scripts for these runbooks are retrieved from storage and assembled into a single file that is passed to the PowerShell workflow engine. For this reason, at the time a runbook job is submitted the parent and descendant runbooks must already be published otherwise an exception will occur during compilation. Currently, the order of publishing also matters: you must publish the child runbooks first and then publish the parent. Similarly, when testing the parent runbook in the SMA authoring page you must first publish the child runbooks and then you can test the parent. Another consequence of this is that you cannot use a variable to pass the name of an child runbook invoked inline: you must always explicitly name the child runbook within the parent runbook.
Here is an example of a runbook that invokes two child runbooks inline: one child runbook returns output and the other child runbook does not return output.
Start a Runbook with Start-SmaRunbook
You can start a runbook in a separate job by using the Start-SmaRunbook cmdlet (which is in the Microsoft.SystemCenter.ServiceManagementAutomation module that comes installed as part of SMA). When you start a child runbook using Start-SmaRunbook a call is made to the SMA web service to start the runbook and a new job is created.
When a child runbook is started in this way the parent runbook does not wait for the child runbook to finish before continuing (asynchronous). This approach is useful in cases when a parent runbook wants to spin off processes and then forget about them. However, it does come at the cost of creating more jobs in the system, which can make troubleshooting somewhat more involved; and it is also more involved if you need to get back output from the child runbook.
Below is an example of a runbook that uses Start-SmaRunbook to start child runbooks:
When you start a child runbook using Start-SmaRunbook the return value is the job id. If you want return data from the child runbook then you need to do work using the job id to learn when the job completes and then extract any output. Here is an example of script that can help you with this (note that for illustration clarity the calls for the Sma cmdlets are not complete in this example and will require connection information). Keep in mind that the child job may not be able to start for some time if there are too many long running jobs in the system already; in this case the loop described below may never complete, so you may want to add some limiting factor such as a timeout after a certain amount of time passes. Also note that if you start several child jobs the system does not guarantee the order in which the jobs will be started.
Comparison of Child Runbooks that are Invoked Inline versus Started with Start-SmaRunbook
Started with Start-SmaRunbook
SMA is a great tool that allows you to create runbooks that can take advantage of the numerous beneficial features of the PowerShell workflow engine. With an understanding of some of the inner workings of SMA and PowerShell workflow and of some best practices you can create high-quality, reliable, and maintainable runbooks. In this post, we have discussed several best practices for defining input parameters, for defining runbook output, and for calling child runbooks. Now that you have read through the information, take the time to experiment with a few simple runbooks in SMA using the examples above so that the concepts presented in this post become obvious to you. Thanks for listening, and have fun putting this new knowledge into practice.