stackstorm 6. 工作流之Mistral

1 Mistral


Mistral是一个用于管理和执行动作流的Openstack项目。Mistral是可以作为一个单独的
mistral服务在StackStorm中安装。一个Mistral工作流可以通过
https://docs.openstack.org/mistral/latest/user/wf_lang_v2.html
被定义为一个StackStorm动作。
表达式语言,例如YAQL被用于格式化变量和条件验证。从StackStorm2.2版本开始,
Jinja2也开始支持YAQL表达式。同样工作簿和工作流定义也是支持的。
在一个动作执行的时候,StackStorm编写Mistral定义并执行工作流。
一个工作流可以调用其他的StackStorm动作作为子任务。StackStorm处理
转化和在Mistral中显式调用并向Mistral轮询来获取执行结果。StackStorm
在工作流中的动作可以被追溯到原始的父动作,即调用工作的动作。

Essential Mistral Links:

Mistral workflow definition language, aka v2 WorkFlow Language
YAQL documentation and YAQL online evaluator
Jinja2 template engine documentation and Jinja2 online evaluator

2 基本工作流


与ActionChains相似,Mistral工作流在/opt/stackstorm/packs//actions
有一个动作元数据文件,工作流定义本身是在/opt/stackstorm/packs//actions/workflows。
让我们用一个非常基本的工作流调用一个StackStorm动作和在工作流完成时通知StackStorm的例子作为开始。
这个文件时在examples中,在/usr/share/doc/st2/examples的位置。

第一个任务叫做run-cmd。它在StackStorm安装的地方,在一个servier上执行了一个shell命令。
一个任务可以直接引用任何注册的StackStorm的动作。在例子中,这个run-cmd任务调用core.local,并传入
cmd作为输入。core.local是一个StackStorm安装时携带的动作。当工作流被调用时,StackStorm将会
在发送工作流给Mistral之前对工作流定定义进行合适地转换。让我们把它存储StackStorm的
/opt/stackstorm/packs/examples/actions/workflows/mistral-basic.yaml


version: '2.0'

examples.mistral-basic:
    description: A basic workflow that runs an arbitrary linux command.
    type: direct
    input:
        - cmd
        - timeout
    output:
        stdout: <% $.stdout %>
    tasks:
        task1:
            action: core.local cmd=<% $.cmd %> timeout=<% $.timeout %>
            publish:
                stdout: <% task(task1).result.stdout %>
                stderr: <% task(task1).result.stderr %>


这是一个与StackStorm动作元数据相对应的例子。用于工作流动作的StackStorm的包叫做examples。
注意工作流在上述定义中以.命名是完全合格的。StackStorm动作运行器是mistral-v2.
StackStorm的entry point指向工作流定义的YAML文件。我们将元数据保存为:
/opt/stackstorm/packs/examples/actions/mistral-basic.yaml

---
description: Run a local linux command
enabled: true
runner_type: mistral-v2
entry_point: workflows/mistral-basic.yaml
name: mistral-basic
pack: examples
parameters:
  cmd:
    required: true
    type: string
  timeout:
    type: integer
    default: 60

下面的可选参数列表可以被定义在工作流动作中。在例子中,这些可选参数被设置为
不可修改的。设置它们为不可修改的是一种良好的实践,即使它们为空。

options    description
workflow    如果定义是一个包含了许多工作流的workbook,这个参数指定了要执行的主工作流。
task        如果工作流是逆序的,这个参数指定了要调用的任务。
context    一个包含额外工作流启动参数的字典。

下一步,运行 st2 action create /opt/stackstorm/packs/examples/actions/mistral-basic.yaml
来创建工作流动作。这将会注册动作流以examples.mistral-basic的形式到StackStorm中。
为了执行工作流,运行: 
st2 run examples.mistral-basic cmd=date -a
而 -a告诉命令无需等待工作流完成即可返回。

如果工作流成功完成,工作流examples.mistral-basic和动作core.local
在StackStorm的动作执行列表中应该有一个succeeded状态。
默认,st2 execution list只返回顶级的执行。这意味着自任务并不会被展现。

+--------------------------+--------------+--------------+-----------+-----------------+---------------+
| id                       | action.ref   | context.user | status    | start_timestamp | end_timestamp |
+--------------------------+--------------+--------------+-----------+-----------------+---------------+
| 54ee54c61e2e24152b769a47 | examples     | stanley      | succeeded | Wed, 25 Feb     | Wed, 25 Feb   |
|                          | .mistral-    |              |           | 2015 23:03:34   | 2015 23:03:34 |
|                          | basic        |              |           | UTC             | UTC           |
+--------------------------+--------------+--------------+-----------+-----------------+---------------+

为了展示子任务,运行:
st2 execution get --show-tasks

+--------------------------+------------+--------------+-----------+------------------------------+------------------------------+
| id                       | action.ref | context.user | status    | start_timestamp              | end_timestamp                |
+--------------------------+------------+--------------+-----------+------------------------------+------------------------------+
| 54ee54c91e2e24152b769a49 | core.local | stanley      | succeeded | Wed, 25 Feb 2015 23:03:37    | Wed, 25 Feb 2015 23:03:37    |
|                          |            |              |           | UTC                          | UTC                          |
+--------------------------+------------+--------------+-----------+------------------------------+------------------------------+

下面是基于先前工作流定义的简单扩展。在这个例子中,我们已经有第二个叫做"task2"的任务。
很自然地可以想到,按照顺序task2将会在task1后面执行。然而,当没有任务属性例如:
on-complete, on-success和on-error是被定义地,任务将会并行。这在Mistral中是可能地,
因为它提供了一个工作流加入控制,这允许我们同步多个并行地工作流分支,并可以巨基它们地数据。

version: '2.0'

examples.mistral-basic-two-tasks-with-notifications:
    description: A basic workflow that runs two Linux commands (one in each task).
    type: direct
    output:
        stdout: <% $.stdout %>
    tasks:
        task1:
            action: core.local cmd="echo task1"
            publish:
                stdout: <% task(task1).result.stdout %>
                stderr: <% task(task1).result.stderr %>
        task2:
            action: core.local cmd="echo task2"
            publish:
                stdout: <% task(task2).result.stdout %>
                stderr: <% task(task2).result.stderr %>

3 发布变量


一个Mistral任务可以产生结果,并将一个任务以变量的形式在其他任务中使用:

tasks:
    get_hostname:
        action: core.local
        input:
            cmd: "hostname"
        publish:
            hostname: <% task(get_hostname).result.stdout %>

在上述的例子中,get_hostname是一个core.local动作,该动作运行命令 hostname。
这个 core.local动作产生了的输出由stdout, stderr, exit_code等字段构成。

我们仅仅将变量stdout发布,以供剩余的任务使用。为了在任务中引用结果,使用
task功能,该功能呢个返回一个包含任务属性的字典,例如: id, state, result
和其他信息。

另一个例子显示如下:

tasks:
    create_new_node:
        action: rackspace.create_vm
        input:
          name: <% $.hostname %>
          flavor_id: <% $.vm_size_id %>
          image_id: <% $.vm_image_id %>
          key_material: <% $.ssh_pub_key %>
          metadata:
            asg: <% $.asg %>
        publish:
          ipv4_address: '<% task(create_new_node).result.result.public_ips[1] %>'
          ipv6_address: '<% task(create_new_node).result.result.public_ips[0] %>'


在上述例子中,动作rackspace.create_vm是一个Python动作,该动作长生了一个result对象。
我们仅仅想要从result对象的public_ips的列表字段中将IP地址发布出去。

请注意result.result不是一个打印错误。这个Python动作提交了一个叫做result的key,用于st2 
动作执行和Mistral 任务函数将Python动作的结果存储到输出字典的result中。

这样发布的变量是可以作为输入参数被工作流中其他任务获取的。在下面的其他任务中使用ipv3_address的例子如下:
tasks:
    # ...

    setup_ipv4_dns:
        action: rackspace.create_dns_record
        wait-before: 1 # delay, in seconds
        input:
          name: '<% $.hostname %>.<% $.asg %>.<% $.domain %>'
          zone_id: <% $.dns_zone_id %>
          type: 'A'
          data: <% $.ipv4_address %>

    # ....


4 一起构造一个复杂的工作流


下面是一个复杂工作流的仿制。在这个仿制中运行了简单的printf和sleep命令,
工作流展示了内迁的工作流,fork和join:
version: "2.0"
name: examples.mistral-workbook-complex
description: A sample workflow that demonstrates nested workflows, forks, and join.

workflows:

    main:
        type: direct
        input:
            - vm_name
            - cpu_cores
            - memory_mb
        output:
            vm_id: <% $.vm_id %>
            ip: <% $.ip %>
        tasks:
            register_dns:
                action: core.local
                input:
                    cmd: "sleep 1; printf 'Registering <% $.vm_name %>...'"
                publish:
                    ip: "10.1.23.99"
                    status_message: "DNS for <% $.vm_name %> is registered."
                on-success:
                    - configure_vm
                    - notify
            create_vm:
                wait-before: 1
                workflow: create_vm
                input:
                    name: <% $.vm_name %>
                    cpu_cores: <% $.cpu_cores %>
                    memory_mb: <% $.memory_mb %>
                publish:
                    vm_id: <% task(create_vm).result.vm_id %>
                    status_message: "VM <% $.vm_name %> is created."
                on-success:
                    - configure_vm
                    - notify
            configure_vm:
                join: all
                workflow: configure_vm
                input:
                    vm_id: <% $.vm_id %>
                    ip: <% $.ip %>
                publish:
                    status_message: "VM <% $.vm_name %> is reconfigured."
                on-success:
                    - close_request
                    - notify
            close_request:
                action: std.noop
                publish:
                    status_message: "VM request is fulfilled."
                on-success:
                    - notify
            notify:
                action: core.local
                input:
                    cmd: "printf '<% $.status_message %>'"

    create_vm:
        type: direct
        input:
            - name
            - cpu_cores
            - memory_mb
        output:
            vm_id: <% $.vm_id %>
        tasks:
            create:
                action: core.local
                input:
                    cmd: "printf 'vm1234'; sleep 5"
                publish:
                    vm_id: <% task(create).result.stdout %>

    configure_vm:
        type: direct
        input:
            - vm_id
            - ip
        tasks:
            add_disks:
                action: core.local
                input:
                    cmd: "sleep 1; printf 'disks created'"
            add_nics:
                action: core.local
                input:
                    cmd: "sleep 1; printf 'nics created'"
            install_apps:
                action: core.local
                input:
                    cmd: "sleep 1; printf 'apps installed'"

在这个工作簿中有多个工作流被定义,工作流作者必须在元数据中指定要执行的工作流:

---
description: Run a series of simulated actions.
enabled: true
entry_point: workflows/mistral-workbook-complex.yaml
name: mistral-workbook-complex
pack: examples
parameters:
  cpu_cores:
    default: 1
    type: integer
  memory_mb:
    default: 1024
    type: integer
  vm_name:
    required: true
    type: string
  workflow:
    default: examples.mistral-workbook-complex.main
    immutable: true
    type: string
runner_type: mistral-v2

为了测试工作流的输出,将元数据文件存储在
/opt/stackstorm/packs/examples/actions/
而工作流文件存储在
/opt/stackstorm/packs/examples/actions/workflows

运行
st2 action create /opt/stackstorm/packs/examples/actions/mistral-workbook-complex.yaml
来创建动作并执行
st2 run examples.mistral-workbook-complex vm_name="vmtest1" -a
用于测试。

5 验证


Mistral 命令行包含了用于执行逻辑高度清晰的工作流YAML文件工作:

# 验证一个工作流
mistral workflow-validate /path/to/workflow.yaml

# 验证一个工作簿
mistral workbook-validate /path/to/workbook.yaml


6 更多的例子


更多工作流的例子在
/usr/share/doc/st2/examples
。这些例子包含了错误处理,重复和重试。

一步一步的实验来在StackStorm重创建工作流请参见:
https://stackstorm.com/2015/07/08/automating-with-mistral-workflow/

更多关于Mistral的细节可以在下面找到:
https://docs.openstack.org/mistral/latest/


以上翻译自:
https://docs.stackstorm.com/mistral.html

你可能感兴趣的:(stackstorm)