If you’ve started playing around with the new wild and wonderful Service Management Automation (SMA) feature of System Center 2012 R2 Orchestrator, you may have noticed that the product includes a bunch of PowerShell modules out of the box for you to use in your SMA runbooks. You may also have noticed that a bunch of these modules represent familiar products, except they have “-Portable”
appended to the end of their module name:
In fact, the full list of out of box modules included in SMA that end in “-Portable” is quite extensive:
So what are these mystery modules, and how do they work? It turns out these modules actually represent a special type of module usable in SMA called a “Portable Module.” Let’s dive into what this type of module is all about:
Portable modules are like regular modules, except for one difference – they don’t contain any functionality. Each portable module reflects a regular PowerShell module, in that it contains the cmdlet stubs of all the cmdlets of its regular PowerShell module counterpart. So, for example, the Azure-Portable module contains all of the cmdlets, cmdlet attributes, cmdlet synopsis, cmdlet help URIs, cmdlet parameters, and cmdlet parameter attributes of the Azure PowerShell module that it represents. It is nearly identical to the Azure module, until you try to run it. That’s because cmdlet functionality is not implemented in portable module cmdlets – instead the cmdlets just try to call their regular PowerShell module counterpart’s cmdlets and spit out an error if the regular PowerShell module is not on the system. For example, here’s what the implementation of Azure-Portable’s Get-AzureVM cmdlet looks like, slightly modified for readability:
Why Use Portable Modules?
So, why does SMA contain these module monstrosities? Simply put, these modules do have their uses. Portable modules are useful when the module which they represent cannot be easily imported into SMA, due to how the module was packaged. For example, a module that you can only get on your local system by installing a product, such as the VMM PowerShell module, may depend on some DLLs which are not in the module directory and are instead somewhere else on the system, placed there by the installer. Of course, these DLLs would not be present on the SMA Runbook Worker that runs runbooks, and so cmdlets in this module would fail to run.
In theory, one could try to import the module, see what dependency it fails on, collect that DLL from somewhere on the system and put it in the module package, repeating this process for all dependencies until the import process succeeds. However, there could be many dependencies making this module package a huge pain to assemble. In addition, PowerShell modules that were installed on a system may depend on registry keys that were set by the installer. Clearly, these registry keys wouldn’t exist on the Runbook Worker machines, and so the module would not work even if one was able to package all its disparate file dependencies into a single folder. Worse yet, cmdlets in the module may try to access these registry keys at run time only, so while importing the module into SMA may succeed, actually executing a cmdlet may still fail!
Portable modules ease this pain, but they don’t fix everything. A portable module is generated with the SMA cmdlet New-SmaPortableModule, which takes in a regular Powershell module and spits out a self-contained SMA module package – something that can be easily imported into SMA. However, as explained above, this portable module package is mostly a stub of the regular module it was created from – if you ever try to run a cmdlet of a portable module, it just tries to run the cmdlet of the regular module it was created against, and if it can’t (usually because the real module isn’t on the Runbook Worker), you’ll see this exception:
In the above, CSAND-SMA is the name of the Runbook Worker host that ran runbook Test1.
The reason these modules are still useful is because they allow you to import and work against some representation of the module within SMA, so that you can take advantage of SMA capabilities that require a module package be imported. Firstly, you can create SMA connections for the imported portable module in SMA, which can be used to manage connection specific info related to the module the portable module represents. In addition, you get design time discoverability for all of the module’s cmdlets and their exact syntax using the insert activity wizard, so you never need to go look up the module’s cmdlets or cmdlet syntax again (although we do include the cmdlet help URIs just in case you want to!)
In summary, think of portable modules as ‘all design, no execution.’
How Can I Use Portable Modules?
As stated above, you never really “use” portable modules during run time -- they are purely meant for design time assistance. You just need to make sure you insert them at design time in a way that will use the regular PowerShell module rather than the portable one at run time. You can do this in two ways. The first way is to install the regular PowerShell module manually onto every runbook worker host, so that the portable module’s cmdlets will be able to call the corresponding regular module’s cmdlet. The second way is to install the regular module on a non-runbook worker host, and have your runbooks remote into this host using an InlineScript, and then use the cmdlets there. The below runbook shows an example of this:
As you can see, it’s the same cmdlet syntax as usual, just wrapped in an InlineScript activity. It’s important to note that InlineScripts run as PowerShell script rather than PowerShell workflow, so don’t expect to be able to do things like check pointing your workflow from within the InlineScript.
How Can I Make Portable Modules?
I’m glad you asked! While SMA ships with a variety of portable modules out of the box, you may come across other PowerShell modules you want to import into SMA but are not easily placed with their dependencies in a single folder and/or depend on the registry due to an installer. Thankfully, the SMA PowerShell module contains the cmdlet ‘New-SmaPortableModule’ which lets you create your own portable modules whenever needed.
To use this cmdlet, install the SMA PowerShell module using the Orchestrator installer, and then open up the PowerShell console. Create a session to the host that has the PowerShell module you want to create a portable module from. Then pass this session as well as the module name to New-SmaPortableModule:
This will create a portable module package that is all zipped up and ready to be imported into SMA. Of course, you can unzip the module package and modify the integration module metadata (such as adding new connection fields for connections of this module) as needed if you desire, and then zip it back up for import into SMA.
Hopefully you now have a better understanding of what portable modules are, why you’d use them, how they work, and how to create your own. For more information on topics covered in this post, check out the links below: