Service Management Automation 中的子 Runbook

在 Service Management Automation(SMA)中,最佳做法是编写可重用的模块化 Runbook,其中包含可由其他 Runbook 使用的离散函数。 父 Runbook 通常会调用一个或多个子 Runbook 来执行所需的功能。 有两种方法可以调用子 Runbook,每个 Runbook 都有明显的差异,因此你可以确定哪种方案最适合你的不同方案。

使用内联执行调用子 Runbook

若要从另一个 Runbook 调用某个内嵌 Runbook,请使用被调用 Runbook 的名称并提供其参数值,就像使用活动或 cmdlet 时一样。 同一 SMA 环境中的所有 Runbook 都可供所有其他 Runbook 以这种方式使用。 父 Runbook 将等待子 Runbook 完成,然后转移到下一行,并直接向父级返回任何输出。

在调用某个内联 Runbook 时,它会在与父 Runbook 所在的同一个作业中运行。 父 Runbook 运行的子 Runbook 的作业历史记录中不会提供相应的指示。 子 Runbook 发生的任何异常和任何流输出将与父级关联。 这会导致作业减少,并使它们更易于跟踪和故障排除,因为子 Runbook 引发的任何异常以及与父 Runbook 作业关联的任何流输出。

发布 runbook 时,它调用的任何子 runbook 都必须已具有已发布的版本。 这是因为在编译 Runbook 时,自动化会生成与任何子 Runbook 的关联。 如果不是,父 Runbook 将显示正确发布,但在启动时会生成异常。 如果发生这种情况,可以重新发布父 Runbook,以正确引用子 Runbook。 如果更改了任何子 Runbook,则无需重新发布父 Runbook,因为关联已创建。

调用内联的子 Runbook 的参数可以是任何数据类型,包括复杂对象,并且没有 JSON 序列化,因为使用管理门户或 Start-SmaRunbook cmdlet 启动 Runbook 时没有 JSON 序列化。

Runbook 类型

Runbook 只能使用与使用内联执行方式的子 Runbook 具有相同 类型的 另一个 Runbook。 这意味着 PowerShell 工作流 Runbook 不能使用 PowerShell Runbook 作为使用内联执行的子级,PowerShell Runbook 不能使用 PowerShell 工作流 Runbook。

使用内联执行调用 PowerShell 工作流子 Runbook 时,只需使用 Runbook 的名称。 调用 PowerShell 子 Runbook 时,必须在其名称前面加上 .\ 以指定脚本位于本地目录中。

示例

下面的示例将调用一个测试子 Runbook,该 Runbook 接受三个参数:一个复杂对象、一个整数和一个布尔值。 该子 Runbook 的输出将分配到某个变量。 在本示例中,子 Runbook 是 PowerShell 工作流 Runbook。

$vm = Get-VM -Name "MyVM" -ComputerName "MyServer"
$output = Test-ChildRunbook -VM $vm -RepeatCount 2 -Restart $true

下面是使用 PowerShell 脚本 Runbook 作为子级的示例。

$vm = Get-VM -Name "MyVM" -ComputerName "MyServer"
$output = .\Test-ChildRunbook.ps1 -VM $vm -RepeatCount 2 -Restart $true

使用 cmdlet 启动子 Runbook

可以使用 Start-SMARunbook cmdlet 通过 Windows PowerShell 启动 Runbook。 从 cmdlet 启动子 runbook 时,父 runbook 会在为子 runbook 创建了作业之后立即移动到下一行。 如果需要检索来自 runbook 的任何输出,则需要使用 Get-SMAJobOutput访问作业。

使用 cmdlet 启动的子 Runbook 的作业会在父 Runbook 的某个独立作业中运行。 这会导致更多的作业,而不是调用工作流内联,增加辅助角色服务器上的开销,并使它们更难跟踪。不过,父级可以启动多个子 Runbook,而无需等待每个 Runbook 完成。 对于调用内嵌子 Runbook 的同一种并行执行,父 Runbook 需要使用并行关键字

使用 cmdlet 启动的子 Runbook 的参数以哈希表形式提供,如 Runbook 参数中所述。 只能使用简单数据类型,不过可以提供凭据资产的名称(如 Credentials中所述)。 如果 Runbook 的参数使用复杂数据类型,则必须内联调用该 Runbook。

下面的示例启动一个具有参数的子 runbook,然后等待它完成。 一旦完成,便由父 runbook 从作业收集其输出。

$webServer = 'https://MyServer'
$port = 9090
$runbookName = "Test-Runbook"
$params = @{"VMName"="MyVM";"RepeatCount"=2;"Restart"=$true}

$job = Start-SmaRunbook -WebServiceEndpoint $webServer -Port $port -Name $runbookName -Parameters $params

$doLoop = $true
While ($doLoop) {
   $job = Get-SmaJob -WebServiceEndpoint $webServer -Port $port -Id $job.Id
   $status = $job.Status
   $doLoop = (($status -ne "Completed") -and ($status -ne "Failed") -and ($status -ne "Suspended") -and ($status -ne "Stopped")
}

Get-SmaJobOutput -WebServiceEndpoint $webServer -Port $port -Id $job.Id -Stream Output

比较调用子 Runbook 的方法

下表汇总了从一个 Runbook 调用另一个 Runbook 的两种方法的差异。

内联 Cmdlet
作业 子 Runbook 在父级所在的同一个作业中运行。 为子 Runbook 创建单独的作业。
执行 父 Runbook 等待子 Runbook 完成,然后再继续。 父 runbook 在启动子 runbook 之后立即继续进行。
输出 父 Runbook 可以直接从子 Runbook 获取输出。 父 runbook 必须从子 runbook 作业检索输出。
Parameters 子 Runbook 参数的值需单独指定,并且可以使用任意数据类型。 子 Runbook 参数的值必须组合成单个哈希表,并且只能包含使用 JSON 序列化的简单、数组和对象数据类型。
发布 在发布父 Runbook 之前必须先发布子 Runbook。 在启动父 Runbook 之前,必须随时发布子 Runbook。

后续步骤