Share via


Service Management Automation:与 Orchestrator 集成

Service Management Automation (SMA) 是 Windows Azure Pack 和 Orchestrator 2012 R2 中的一项功能。SMA 和 Orchestrator 均为实现 IT 流程自动化、业务流程和集成而设计,两者的功能和使用方案均受到用户的广泛认可(参见这篇讨论 SMA 与 Orchestrator 的文章)。通常情况下,SMA 最适于在微软云操作系统环境中使用,而 Orchestrator 则最好在传统数据中心环境中使用。正在将某些传统工作负载迁移到云中的 IT 团队可能会发现,利用 SMA 和 Orchestrator 非常有益;在这种情况下,将一些端到端流程从 SMA 扩展到 Orchestrator 以及从 Orchestrator扩展到 SMA 可能是比较普遍的现象。

在本文中,我们将讨论如何集成 SMA 与 Orchestrator。尤其是,我将会重点介绍 SMA Runbook 如何调用 Orchestrator Runbook、Orchestrator Runbook 如何调用 SMA Runbook,以及各种输入参数和返回数据。两种场景均使用产品附带的 PowerShell 模块,以及各个产品呈现的 OData Web 服务端点。

另外,还应阅读如何从 SMA Runbook 调用 Orchestrator 系列(作者:Tiander Turpijn)的其他帮助文章:参见《从 SMA 调用 Orchestrator Runbook》第 1 部分第 2 部分

PowerShell 模块 集成 SMA Orchestrator

为了简化 SMA 与 Orchestrator 的集成过程,我们创建了 PowerShell 模块,并使用命令呈现通过各项 OData Web 服务提供的重要功能。

  • SMA
  • Microsoft.SystemCenter.ServiceManagementAutomation       模块可作为独立于 Orchestrator       2012 R2 安装程序的一个项目安装到任何主机上。建议通过这种方式安装此模块。
  • 或者,如果安装 SMA(从 Orchestrator       2012 R2 安装程序),那么 ServiceManagementAutomation       模块将被预先导入到 SMA 中,同时被安装到 SMA 主机(位于 C:\inetpub\Service       Management Automation\Modules)上。
  • Orchestrator
  • 如果安装 SMA,那么 OrchestratorService       模块将被预先导入到 SMA 中,同时被安装到 SMA 主机(位于 C:\inetpub\Service       Management Automation\Modules)上。如果愿意的话,您可以将该模块从此位置复制到任何其他主机。

接下来的两个图显示了各模块中提供的命令。

OrchestratorService module cmdlets

ServiceManagementAutomation module cmdlets

SMA 调用Orchestrator Runbook

您需要在调用 Orchestrator Runbook 的所有 SMA Runbook 中均采用几个关键步骤;这些步骤如下:

  • 在 SMA 与 Orchestrator 之间创建连接
  • 获取 Orchestrator Runbook
  • 使用/不使用输入参数启动 Orchestrator Runbook
  • 监控生成的 Orchestrator 作业直至其完成
  • 获取 Orchestrator Runbook 实例返回的所有数据

下面我们来更加详细地介绍各个部分。为便于进行说明,我们将从名为 Start-ScoRunbook 的 SMA Runbook 查看 PowerShell 工作流代码。下面的方框中展示了整个 Runbook 脚本(另外,您也可以单击此处下载Runbook,然后将其导入到 SMA 中)。

001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 ######################################################################## # Copyright (c) Microsoft. All rights reserved. # This code is licensed under the Microsoft Public License. # THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER # EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS # FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. ######################################################################## <# .SYNOPSIS This runbook starts an Orchestrator runbook with or without parameters and gets back any output. .DESCRIPTION This runbook illustrates how to start a runbook in System Center Orchestrator, pass in parameters, and get back return data. If the Orchestrator runbook has output, then this runbook will return it as a hashtable with key/value pairs, where the key is the output parameter name .PARAMETER RunbookPath String. The full path to the runbook as defined in Orchestrator. For example, \folder1\folder2\runbookname. .PARAMETER InputParams Object. Input parameters formatted as PSCustomObject with key/value pairs. .PARAMETER JobCheckIntervalInSeconds Int. The amount of time, in seconds, to sleep between attempts to check the job for completeness. Set this to greater than the expected run time of the job. .NOTES The runbook expects to connect with the web service for an installation of Orchestrator 2012 or 2012 R2. The runbook assumes that you have created an Automation Connection asset named "OrchestratorConnection" with the information required to connect with the Orchestrator web service. #>  workflow Start-ScoRunbook {     [OutputType( [hashtable] )]     # define the input parameters to this runbook     param (         [Parameter(Mandatory=$true)]             [string] $RunbookPath,         [Parameter(Mandatory=$false)]             [object] $InputParams,         [Parameter(Mandatory=$false)]             [int] $JobCheckIntervalInSeconds     )          # get the Orchestrator connection asset     $con = Get-AutomationConnection -Name 'OrchestratorConnection'     # create a Credential object     $securepassword = ConvertTo-SecureString -AsPlainText -String $con.UserPassword -Force     $domainuser = $con.UserDomain + "\" + $con.UserName     $creds = New-Object -TypeName System.Net.NetworkCredential -ArgumentList ($domainuser, $securepassword)     # create the URL for the Orchestrator service     $url = Get-OrchestratorServiceUrl -Server $con.ServerName     # get the SCO runbook we want to start     $runbook = Get-OrchestratorRunbook -ServiceUrl $url -Credentials $creds -RunbookPath $RunbookPath     if ($runbook -eq $null) {         $msg = "Orchestrator runbook '$RunbookPath' could not be retrieved."         Write-Error -message $msg         Throw $msg     }     else {         # start the runbook job         if ($InputParams -ne $null) {             # convert the input param names to their associated GUIDs             $RBInputWithIds = getParamObjectWithIds -RBInputWithNames $InputParams -runbook $runbook                         # start the runbook with input parameters and get the job returned             $job = Start-OrchestratorRunbook -Runbook $runbook -Credentials $creds -Parameters $RBInputWithIds         }         else {             # start the runbook without any input parameters and get the job returned             $job = Start-OrchestratorRunbook -Runbook $runbook -Credentials $creds         }                     # if a job has been created then get any output         if ($job -eq $null) {             $msg = "Orchestrator runbook job is null: no job was created."             Write-Error -message $msg             Throw $msg         }         else {          # get any output             $out = getJobOutput -Job $job -Creds $creds -JobCheckIntervalInSeconds $JobCheckIntervalInSeconds             # return the output object if there is output             if ($out -ne $null) {                 Write-Output $out             }         }     }         #     # Function that takes an input parameter object that has parameter names and values     # and replaces the names with the ids     #     function getParamObjectWithIds     {         param (             [object] $RBInputWithNames,             [object] $runbook         )                 # convert the PSCustomObject to a hashtable         $NamesHt = @{}         $RBInputWithNames.psobject.properties | Foreach { $NamesHt[$_.Name] = $_.Value }                 # get the runbook parameters         $RBParams = $runbook.Parameters                 # create new input parameter hashtable with parameter ids as keys         $RBInputWithIds = @{}         foreach($key in @($NamesHt.keys)) {             foreach ($pm in $RBParams) {                  if ($pm.Name -eq $key) {                      $RBInputWithIds.Add($pm.Id,$NamesHt[$key])                  }             }         }                 # output the new parameter hashtable         Write-Output $RBInputWithIds     }         #     # Function that gets the runbook job output     #     function getJobOutput     {         param (             [object] $Job,             [object] $Creds,             [int] $JobCheckIntervalInSeconds         )                 # assure the job is complete         while( ($job.Status -eq "Running") -or ($job.Status -eq "Pending") ) {             Start-Sleep -s $JobCheckIntervalInSeconds             $job = Get-OrchestratorJob -jobid $job.Id -serviceurl $job.Url_Service -credentials $creds         }                 # get the runbook instance that has the job data         $instance = Get-OrchestratorRunbookInstance -Job $job -Credentials $creds         if ($instance -eq $null) {             $msg = "Orchestrator runbook instance is null."             Write-Error -message $msg             Throw $msg         }         else {             # there are instance parameters only if the runbook has input and/or output parameters             $instparams = Get-OrchestratorRunbookInstanceParameter -RunbookInstance $instance -Credentials $creds             if ($instparams -ne $null) {                 # any output will be in a hashtable                 $out = @{}                 # look through the runbook parameters for any that are for output                 foreach ($instparam in $instparams) {                     if ($instparam.Direction -eq "Out") {                         # write the output value (always a string, interger, date, or boolean)                         $out.Add($instparam.Name,$instparam.Value)                     }                 }                 Write-Output $out             } else {                 Write-Verbose -message "The runbook has no output." -Verbose                 Write-Output $null             }         }     }     }

在SMA 与Orchestrator 之间创建连接并获取Orchestrator Runbook

上述代码的第一部分显示如何创建 SMA 到 Orchestrator 的连接并获取 Orchestrator Runbook。在编写 Runbook 之前,我创建了一项 SMA 连接设置,其中包含用于连接 Orchestrator Web 服务的参数(阅读此文章以了解有关 Orchestrator Web 服务的更多信息)。

SMA Connection Setting for connecting with Orchestrator

随 SMA 一同安装的 Get-AutomationConnection 活动用于检索连接对象。我们将从该连接对象提取 UserDomain、UserName 和 UserPassword 字段,以便用于创建用来对 Orchestrator 进行身份验证的凭据对象。此外,我们还会提取 ServerName,Get-OrchestratorServiceUrl 命令用它来为 Orchestrator Web 服务创建完整 URL。有了 URL、凭据和 Runbook 路径,接着我们又使用 Get-OrchestratorRunbook 命令获取 Orchestrator Runbook 对象。

启动 Orchestrator Runbook

由于我们已经具备 Runbook 对象以及所有输入参数,因此可以随时启动 Runbook。要启动 Runbook,我们需要使用 Start-OrchestratorRunbook 命令,该命令将获取 Runbook 对象、凭据及所有输入参数。如果包含 Runbook 输入参数,我们首先必须获取每个命名参数的 GUID,然后创建一个包含 GUID 和值的 hashtable(由 getParamObjectWithIds 函数执行此操作)。

监控Orchestrator 作业的完成情况并获取所有输入内容

如果 Start-OrchestratorRunbook 执行成功,它将返回 Orchestrator 作业对象。接下来,需要监控改作业的完成情况并获取所有输入内容:由 getJobOutput 函数执行此任务。

要监控某项作业并确定其是否已经完成,需要使用 Get-OrchestratorJob 命令,直到作业状态为“正在运行”或“正在挂起”为止。注意,睡眠间隔可配置:您会希望确保该数值大于预期作业运行时间。如果该作业并未处于上述任一状态,则说明其已经达到最终状态,我们可以尝试关联 Runbook 实例与该作业,这样我们就能提取 Direction 元数据为 Out(其中包含 Runbook 输出)的任何 Runbook 实例参数。如果包含输出参数,那么我们需要将其打包到 hashtable 并返回。

从Orchestrator 调用SMA Runbook

调用 SMA Runbook 的 Orchestrator Runbook 的主要逻辑与上面所述的逻辑非常类似。

  • 在 Orchestrator 与 SMA 之间创建连接
  • 使用/不使用输入参数启动 SMA Runbook
  • 监控生成的 SMA 作业直至其完成
  • 获取 SMA 作业返回的所有输出数据

此 Runbook 与上一部分讨论的 Runbook 之间的主要区别在于,此 Orchestrator Runbook 将包含使用 SMA PowerShell 模块的 PowerShell 脚本的所有核心逻辑。此脚本将包含在 Orchestrator Run .Net 脚本活动(单击此处下载该脚本)中。由于 SMA PowerShell 模块需要使用 64 位 PowerShell 进程才能运行,而 Orchestrator 仅限于 32 位进程使用,该脚本使用 PowerShell Remoting 在安装 ServiceManagementAutomation 模块的 64 位 Windows Server 上运行 SMA 命令。请记得在远程计算机的 PowerShell 控制台中运行 “Set-ExecutionPolicy RemoteSigned”,以便允许远程操作。

接下来的屏幕截图显示了一种包含输入参数的简单 Orchestrator Runbook,使用 Run .Net 脚本活动运行该脚本,调用 SMA,然后返回所有输入内容。通常情况下,您的 Runbook 比该 Runbook 要复杂得多,但集成 SMA 的主要逻辑将包含在这个单一 Run .Net 脚本活动中。

Orchestrator runbook that calls SMA

对于脚本中的连接和凭据值,您可能希望使用 Orchestrator 全局设置中存储的变量,以便在大量 Runbook 中重用此连接信息。

Global settings for SMA connection fields

用于启动SMA Runbook 、监控作业及获取返回数据的PowerShell 脚本

您可以在下面的方框中查看整个脚本。此脚本首先在 PowerShell ISE 中进行编写和测试,接着将被粘贴到 Run .Net 脚本活动中。

001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 $ErrorActionPreference = "Stop" try {     # credentials     $user = "domain\username"     $pwd = ConvertTo-SecureString –String "password" –AsPlainText -Force     $cred = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $user, $pwd     # web service endpoint     $computername = "sma-server"     $wsep = "https://$computername"     $port = "9090"         # create persistent connection to remote computer     $session = New-PSSession -ComputerName $computername -Credential $cred     # run the script block in the remote session and get back the output     $out = Invoke-Command -Session $session -ArgumentList $cred,$wsep,$port -scriptblock {         $cred = $args[0]         $wsep = $args[1]         $port = $args[2]                  # set the runbook name and any input parameters         $RBName = "SMARunbook"         $params = @{"Param1"="StringValue";"Param2"=123}         # start the SMA runbook         $thejobid = Start-SmaRunbook -Name $RBName -Parameters $params -WebServiceEndpoint $wsep -Port $port -AuthenticationType Basic -Credential $cred         # monitor the SMA job until completed         $shouldLoop = $true         while($shouldLoop) {             # the sleep interval, in seconds, should be greater than the expected run time of the SMA job             $sleepinterval = 5             Start-Sleep -s $sleepinterval             $job = Get-SmaJob -Id $thejobid -WebServiceEndpoint $wsep -Port $port -AuthenticationType Basic -Credential $cred             $status = $job.JobStatus             $shouldLoop = (($status -ne "Completed") -and ($status -ne "Failed") -and ($status -ne "Suspended") -and ($status -ne "Stopped"))         }         # get the job output         $jobout = Get-SmaJobOutput -Id $thejobid -Stream Output -WebServiceEndpoint $wsep -Port $port -AuthenticationType Basic -Credential $cred         $jobout.StreamText     }     $out } catch {     Throw $_.Exception }

脚本的第一部分创建凭据和连接对象。接着,又为远程服务器创建连接会话。

紧接着是脚本的主要部分,即使用 Invoke-Command 命令执行远程计算机 PowerShell 会话中的脚本块。使用 –ArgumentList 参数将各参数传递到该脚本块。

在该脚本块中,使用 Start-SmaRunbook 命令启动 SMA Runbook,然后以 hashtable 对象的形式向其传递参数。

Start-SmaRunbook 命令返回作业 ID,此作业 ID 将用于通过 Get-SmaJob 命令对作业实施监控。当作业状态达到最终状态时,接着使用 Get-SmaJobOutput 返回的对象中的 StreamText 属性来获取所有输出内容。注意,在本示例中,我们并未检查最终状态是否确实为“已完成”,因此您将需要添加逻辑以应对 Runbook 处于某种其他状态的情形。

同时注意,Get-SmaJob 命令位于单一集合中,不保证返回的记录的顺序按时间排序。如果希望它们按时间排序,则下列 PowerShell 脚本可能会有所帮助:

Get-SmaJobOutput <params here> | %{ $_ } | sort StreamTIme

要将脚本输出内容提取到 Orchestrator 数据总线,以便 Orchestrator Runbook 中的其他活动使用这些输出内容,需要配置 Run .Net 脚本活动 Published Data,将脚本的 “out” 变量内容置于名为 “Return from SMA” 的数据总线属性中。

Set the returned data from the script

小结

大家可以看到,一旦您了解连接 SMA 与 Orchestrator、启动 Runbook、监控作业及获取输出数据的技术后,创建端到端进程的目标将变得相当简单明了。您现在就可以在调用 Orchestrator 的 SMA 中或调用 SMA 的 Orchestrator 中编写一个简单的 Runbook;从这些试验中,您应该对这项技术有了充分的基本了解,因此可以构建更加复杂的场景了。