From 460f5d691bb4e87e60dcf0b4b2cca86fb7b51288 Mon Sep 17 00:00:00 2001 From: Dmitri Zimine Date: Sun, 5 Oct 2014 13:25:16 -0700 Subject: [PATCH] Add documentation - part 2 Migrate DSL specs from wiki Coming up next: setup autodocs to for REST v2 Change-Id: I6df52adcbf0f22d506c3c08e48318f0a9a6f60fe --- doc/source/dsl/dsl_v1.rst | 406 +++++++++- doc/source/dsl/dsl_v2.rst | 707 ++++++++++++++++++ doc/source/dsl/index.rst | 2 +- doc/source/img/Mistral_direct_workflow.png | Bin 0 -> 14571 bytes doc/source/img/Mistral_reverse_workflow.png | Bin 0 -> 12431 bytes .../img/Mistral_workbook_namespacing.png | Bin 0 -> 33293 bytes 6 files changed, 1112 insertions(+), 3 deletions(-) create mode 100644 doc/source/img/Mistral_direct_workflow.png create mode 100644 doc/source/img/Mistral_reverse_workflow.png create mode 100644 doc/source/img/Mistral_workbook_namespacing.png diff --git a/doc/source/dsl/dsl_v1.rst b/doc/source/dsl/dsl_v1.rst index 8dbc89ed..04fcd609 100644 --- a/doc/source/dsl/dsl_v1.rst +++ b/doc/source/dsl/dsl_v1.rst @@ -1,2 +1,404 @@ -DSL v1 (deprecated) -=================== \ No newline at end of file +Mistral DSL specification +------------------------- + +Version 0.1 + +Main objects +~~~~~~~~~~~~ + +- **Namespace** +- **Action** +- **Workflow** +- **Task** +- **Trigger** + +Namespaces +~~~~~~~~~~ + +Contains a list of namespaces grouping custom (ad-hoc) actions. For +example, it's possible to create namespace "Nova" that would provide +actions "createVM", "deleteVM" and similar for VM management in +OpenStack. + +Attributes +^^^^^^^^^^ + +All attributes are inside main keys of **Namespaces** - **namespaces +names**. Attributes of an individual namespace are: + +- **class** - currently Mistral supports the following action classes + out of the box: std.http, std.mistral\_http, std.echo, std.email, + std.ssh, this is an optional attribute +- **base-parameters** - dictionary depending on type of the namespace, + this parameter is optional. Values of these parameters apply to all + actions inside the namespace. For example for std.http it can contain + url, method, body and headers. +- **actions** - list of actions provided by this namespace. + +YAML example: +^^^^^^^^^^^^^ + +| ``Namespaces:`` +| ``  Nova:`` +| ``    class: std.http`` +| ``    base-parameters:`` +| ``      method: GET`` +| ``    actions:`` +| ``      create-vm:`` +| ``      ......`` +| ``      delete-vm:  `` +| ``      .....`` + +Action +~~~~~~ + +A function provided by specific namespace. + +Attributes +^^^^^^^^^^ + +- **name** - action name (string without space, mandatory attribute). +- **base-parameters** - dictionary whose structure is defined by action + class (or namespace class if defined). For std.http class it contains + url, method, body and headers according to HTTP protocol + specification. +- **parameters** - list containing parameter names which should or + could be specified in task. This attribute is optional and used only + for documenting purposes. +- **output** - dictionary-transformer for action output to send this + output next to task. Keys of this dictionary will be included in task + result, values are pure YAQL or inline YAQL expressions per key which + define how the specific output should be retrieved from raw output + (from action). See more about YAQL at + https://pypi.python.org/pypi/yaql/0.3 + +YAML example: +^^^^^^^^^^^^^ + +| ``create-vm:`` +| ``  base-parameters:`` +| ``    url: servers`` +| ``  parameters:`` +| ``    - name`` +| ``    - server_name  `` +| ``  output:`` +| ``    vm_id: $.content.server.id`` + +Workflow +~~~~~~~~ + +Attributes +^^^^^^^^^^ + +- **tasks** - list of tasks in this workflow, each task represents a + computational step in the workflow. + +YAML example: +^^^^^^^^^^^^^ + +| `` Workflow:`` +| ``   tasks:`` +| ``     create-vms:`` +| ``     .....`` +| ``     attache-volumes: `` +| ``     .....`` + +Task +~~~~ + +Represents a step in workflow, for example creating the VM + +Attributes +^^^^^^^^^^ + +- **action** - name of action to perform +- **requires** - list of tasks which should be execute before this + tasks, or list of task names as a keys and condition as a value, this + is optional parameter +- **parameters** - actual parameters for the task, each value can be + either some number, string etc, or YAQL expression to retrieve value + from task context +- **on-success** - task which will be scheduled on execution after + current task has finished with state 'SUCCESS' +- **on-error** - task which will be scheduled on execution after + current task has finished with state 'ERROR' +- **on-finish** - task which will be scheduled on execution after + current task has finished + +YAML example: +''''''''''''' + +| ``create-vm:`` +| ``  action: Nova.create-vm`` +| ``  parameters:`` +| ``    image_id: $.image_id`` +| ``    flavor_id: 42`` +| ``  requires:`` +| ``    task2: '$.value2 = 123'`` +| ``    task4: '$.value4 = 122'`` +| ``  on-success: task3`` + +Triggers +~~~~~~~~ + +Using triggers it is possible to run workflows according to specific +rules: periodically setting a cron (http://en.wikipedia.org/wiki/Cron) +pattern or on external events like ceilometer alarm. + +Attributes +^^^^^^^^^^ + +- **type** - can be PERIODIC, CEILOMETER\_ALARM +- **tasks** - list of tasks which should be execute on trigger +- **parameters** - list of task parameters + +YAML example: +^^^^^^^^^^^^^ + +| ``triggers:`` +| ``  backup-vm:`` +| ``    type: periodic`` +| ``    tasks: [create_backup, delete_old_backup] `` +| ``    parameters:`` +| ``      cron-pattern: 1 0 * * *`` + +Full YAML example: +~~~~~~~~~~~~~~~~~~ + +This example requires the following properties provided in execution context: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. - nova\_url ## url to Nova service, e.g. http://0.0.0.0:8774/v3 +#. - server\_name ## Name you want to give to new instance +#. - image\_id ## image id from Glance service +#. - flavor\_id ## flavor id - type of instance hardware +#. - ssh\_username ## username of your VM +#. - ssh\_password ## password to your VM +#. - admin\_email ## email address to send notifications to +#. - from\_email ## email address to send notifications from +#. - smtp\_server ## SMTP server to use for sending emails (e.g. + smtp.gmail.com:587) +#. - smtp\_password ## password to connect to SMTP server + +| ``Namespaces:`` +| `` Nova:`` +| ``   # Nova actions for creating VM, retrieving IP and VM deleting.`` +| ``   class: std.http`` +| ``   actions:`` +| ``     createVM:`` +| ``       base-parameters:`` +| ``         url: '{$.nova_url}/{$.project_id}/servers'`` +| ``         method: POST`` +| ``         headers:`` +| ``           X-Auth-Token: $.auth_token`` +| ``           Content-Type: application/json`` +| ``         body:`` +| ``           server:`` +| ``             name: $.server_name`` +| ``             imageRef: $.image_id`` +| ``             flavorRef: $.flavor_id`` +| ``       output:`` +| ``         vm_id: $.content.server.id`` +| `` `` +| ``     getIP:`` +| ``       base-parameters:`` +| ``         url: '{$.nova_url}/{$.project_id}/servers/{$.vm_id}'`` +| ``         method: GET`` +| ``         headers:`` +| ``           X-Auth-Token: $.auth_token`` +| ``       output:`` +| ``         vm_ip: "$.content.server.addresses.novanetwork.where($.'OS-EXT-IPS:type' = 'floating')[0].addr"`` +| `` `` +| ``     deleteVM:`` +| ``       base-parameters:`` +| ``         url: '{$.nova_url}/{$.project_id}/servers/{$.vm_id}'`` +| ``         method: DELETE`` +| ``         headers:`` +| ``           X-Auth-Token: $.auth_token`` +| ``       output:`` +| ``         status: $.status`` +| `` `` +| `` Server:`` +| ``   actions:`` +| ``     # HTTP request to the server.`` +| ``     calcSumm:`` +| ``       class: std.http`` +| ``       base-parameters:`` +| ``         url: '``\ ```http://`` `__\ ``{$.vm_ip}:5000/summ'`` +| ``         method: POST`` +| ``         body:`` +| ``           arguments: $.arguments`` +| ``       output:`` +| ``         summ_result: $.content.result`` +| `` `` +| `` Ssh:`` +| ``   class: std.ssh`` +| ``   base-parameters:`` +| ``     host: $.vm_ip`` +| ``     username: $.username`` +| ``     password: $.password`` +| ``   actions:`` +| ``     # Simple SSH command.`` +| ``     waitSSH:`` +| ``       base-parameters:`` +| ``         cmd: 'ls -l'`` +| `` `` +| ``     # SSH command to run the server.`` +| ``     runServer:`` +| ``       base-parameters:`` +| ``         cmd: 'nohup python ~/web_app.py > web_app.log &'`` +| `` `` +| ``Workflow:`` +| `` tasks:`` +| ``   # Create a VM (request to Nova).`` +| ``   createVM:`` +| ``     action: Nova.createVM`` +| ``     parameters:`` +| ``       server_name: $.server_name`` +| ``       image_id: $.image_id`` +| ``       flavor_id: $.flavor_id`` +| ``       nova_url: $.nova_url`` +| ``       project_id: $.project_id`` +| ``       auth_token: $.auth_token`` +| ``     publish:`` +| ``       vm_id: vm_id`` +| ``     on-success: waitForIP`` +| ``     on-error: sendCreateVMError`` +| `` `` +| ``   # Wait till the VM is assigned with IP address (request to Nova).`` +| ``   waitForIP:`` +| ``     action: Nova.getIP`` +| ``     retry:`` +| ``       count: 10`` +| ``       delay: 10`` +| ``     publish:`` +| ``       vm_ip: vm_ip`` +| ``     parameters:`` +| ``       nova_url: $.nova_url`` +| ``       project_id: $.project_id`` +| ``       auth_token: $.auth_token`` +| ``       vm_id: $.vm_id`` +| ``     on-success: waitSSH`` +| ``     on-error: sendCreateVMError`` +| `` `` +| ``   # Wait till operating system on the VM is up (SSH command).`` +| ``   waitSSH:`` +| ``     action: Ssh.waitSSH`` +| ``     retry:`` +| ``       count: 10`` +| ``       delay: 10`` +| ``     parameters:`` +| ``       username: $.ssh_username`` +| ``       password: $.ssh_password`` +| ``       vm_ip: $.vm_ip`` +| ``     on-success: runServer`` +| ``     on-error: sendCreateVMError`` +| `` `` +| ``   # When SSH is up, we are able to run the server on VM (SSH command).`` +| ``   runServer:`` +| ``     action: Ssh.runServer`` +| ``     parameters:`` +| ``       vm_ip: $.vm_ip`` +| ``       username: $.ssh_username`` +| ``       password: $.ssh_password`` +| ``     on-success: calcSumm`` +| ``     on-error: sendCreateVMError`` +| `` `` +| ``   # Send HTTP request on server and calc the result.`` +| ``   calcSumm:`` +| ``     action: Server.calcSumm`` +| ``     retry:`` +| ``       count: 10`` +| ``       delay: 1`` +| ``     parameters:`` +| ``       arguments:`` +| ``         - 32`` +| ``         - 45`` +| ``         - 23`` +| ``       vm_ip: $.vm_ip`` +| ``     publish:`` +| ``       result: summ_result`` +| ``     on-finish: sendResultEmail`` +| `` `` +| ``   # In case of createVM error send e-mail with error message.`` +| ``   sendResultEmail:`` +| ``     action: std.email`` +| ``     parameters:`` +| ``       params:`` +| ``         to: [$.admin_email]`` +| ``         subject: Workflow result`` +| ``         body: |`` +| ``           Workflow result of execution {$.__execution.id} is {$.result}`` +| `` `` +| ``           -- Thanks, Mistral Team.`` +| ``       settings:`` +| ``         smtp_server: $.smtp_server`` +| ``         from: $.from_email`` +| ``         password: $.smtp_password`` +| ``     on-finish: deleteVM`` +| `` `` +| ``   # In case of createVM error send e-mail with error message.`` +| ``   sendCreateVMError:`` +| ``     action: std.email`` +| ``     parameters:`` +| ``       params:`` +| ``         to: [$.admin_email]`` +| ``         subject: Workflow error`` +| ``         body: |`` +| ``           Failed to create a VM in execution {$.__execution.id}`` +| `` `` +| ``           -- Thanks, Mistral Team.`` +| ``       settings:`` +| ``         smtp_server: $.smtp_server`` +| ``         from: $.from_email`` +| ``         password: $.smtp_password`` +| ``     on-finish: deleteVM`` +| `` `` +| ``   # Destroy the VM (request to Nova).`` +| ``   deleteVM:`` +| ``     action: Nova.deleteVM`` +| ``     parameters:`` +| ``       nova_url: $.nova_url`` +| ``       project_id: $.project_id`` +| ``       auth_token: $.auth_token`` +| ``       vm_id: $.vm_id`` + +Initial execution context +^^^^^^^^^^^^^^^^^^^^^^^^^ + +| `` {`` +| ``   "nova_url": ``\ \ ``,`` +| ``   "image_id": ``\ \ ``,`` +| ``   "flavor_id": ``\ \ ``,`` +| ``   "server_name": ``\ \ ``,`` +| ``   "ssh_username": ``\ \ ``,`` +| ``   "ssh_password": ``\ \ ``,`` +| ``   "admin_email": ``\ \ ``,`` +| ``   "from_email": ``\ \ ``,`` +| ``   "smtp_server": ``\ \ ``,`` +| ``   "smtp_password": ``\ \ ``,`` +| `` }`` + +**When a workflow starts Mistral also adds execution information into +the context so the context looks like the following:** + +| `` {`` +| ``   "nova_url": TBD,`` +| ``   "image_id": TBD,`` +| ``   "image_id": ``\ \ ``,`` +| ``   "flavor_id": ``\ \ ``,`` +| ``   "server_name": ``\ \ ``,`` +| ``   "ssh_username": ``\ \ ``,`` +| ``   "ssh_password": ``\ \ ``,`` +| ``   "admin_email": ``\ \ ``,`` +| ``   "from_email": ``\ \ ``,`` +| ``   "smtp_server": ``\ \ ``,`` +| ``   "smtp_password": ``\ \ ``,`` +| ``   "__execution": {`` +| ``     "id": "234234",`` +| ``     "workbook_name" : "my_workbook",`` +| ``     "project_id": "ghfgsdfasdfasdf"`` +| ``     "auth_token": "sdfljsdfsdf-234234234",`` +| ``     "trust_id": "oiretoilkjsdfglkjsdfglkjsdfg"`` +| ``   }`` +| `` }`` diff --git a/doc/source/dsl/dsl_v2.rst b/doc/source/dsl/dsl_v2.rst index 2c63fffb..04822b87 100644 --- a/doc/source/dsl/dsl_v2.rst +++ b/doc/source/dsl/dsl_v2.rst @@ -1,2 +1,709 @@ Mistral DSL v2 specification ---------------------------- + +**NOTE**: DSL described in this document might slightly change within a +short period of time (2-3 weeks) and should be now considered +**experimental**. Mistral team is now actively working on stabilization. + +Introduction +~~~~~~~~~~~~ + +Current document fully describes Domain Specific Language (DSL) version +2 of Mistral Workflow Service. Since version 1 issued in May 2014 +Mistral team completely reworked the language pursuing with the goal in +mind to make it easier to understand while more consistent and flexible. + +Unlike Mistral DSL v1 this second version of DSL assumes that all +entities that Mistral works with like workflows, actions and triggers +are completely independent in terms of how they're referenced and +accessed through API (and also Python Client API and CLI). Workbooks, +the entity that can combine combine workflows/actions/triggers still +exist in the language but only for namespacing and convenience purposes. +See `Workbooks section <#Workbooks>`__ for more details. + +All DSL consists of the following main object(entity) types that will be +described in details next: + +- `Workflows <#Workflows>`__ +- `Actions <#Actions>`__ +- `Triggers <#Triggers>`__ + +Prerequisites +~~~~~~~~~~~~~ + +Mistral DSL is fully based on YAML and knowledge of YAML is a plus for +better understanding of the material in this specification. It also +takes advantage of YAQL query language to define expressions in +workflow, action and trigger definitions. + +- Yet Another Markup Language (YAML): http://yaml.org +- Yet Another Query Language (YAQL): + https://pypi.python.org/pypi/yaql/0.3 + +Workflows +~~~~~~~~~ + +Workflow is the main building block of Mistral DSL, the reason why the +project exists. Workflow represents a process that can be described in a +various number of ways and that can do some job interesting to the end +user. Each workflow consists of tasks (at least one) describing what +exact steps should be made during workflow execution. + +YAML example +'''''''''''' + +| ``---`` +| ``version: '2.0'`` +| ``create_vm:`` +| ``  description: Simple workflow sample`` +| ``  type: direct`` +| ``  input: # Input parameter declarations`` +| ``    - vm_name`` +| ``    - image_ref`` +| ``    - flavor_ref`` +| ``  output: # Output definition`` +| ``    vm_id: $.vm_id`` +| ``  tasks:`` +| ``    create_server:`` +| ``      action: nova.servers_create name={$.vm_name} image={$.image_ref} flavor={$.flavor_ref}`` +| ``      publish:`` +| ``        vm_id: $.id`` +| ``      on-success:`` +| ``        - wait_for_instance`` +| ``    wait_for_instance:`` +| ``      action: nova.servers_find id={$.vm_id} status='ACTIVE'`` +| ``      policies:`` +| ``        retry:`` +| ``          delay: 5`` +| ``          count: 15`` + +Workflow Types +^^^^^^^^^^^^^^ + +Mistral DSL v2 introduces different workflow types and the structure of +each workflow type varies according to its semantics. Currently, Mistral +provides two workflow types: + +- `Direct workflow <#direct-workflow>`__ +- `Reverse workflow <#reverse-workflow>`__ + +See corresponding sections for details. + +Common Workflow Attributes +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- **type** - Workflow type. Either 'direct' or 'reverse'. *Required*. +- **description** - Arbitrary text containing workflow description. + *Optional*. +- **input** - List defining required input parameter names. *Optional*. +- **output** - Any data structure arbitrarily containing YAQL + expressions that defines workflow output. May be nested. *Optional*. +- **task-defaults** - Default settings for some of task attributes + defined at workflow level. *Optional*. Corresponding attribute + defined for a specific task always takes precedence. Specific task + attributes that could be defined in **task-defaults** are the + following: + + - **on-error** + - **on-success** + - **on-complete** + - **policies** + +- **tasks** - Dictionary containing workflow tasks. See below for more + details. *Required*. + +Tasks +^^^^^ + +Task is what a workflow consists of. It defines a specific computational +step in the workflow. Each task can optionally take input data and +produce output. In Mistral DSL v2 task can be associated with an action +or with calling a workflow. In the example below there are two tasks of +different types: + +.. code-block:: yaml + + action_based_task: +  action: std.http url='openstack.org' + workflow_based_task: +   workflow: backup_vm_workflow vm_id={$.vm_id} + + +Actions will be explained below in a individual paragraph but looking +ahead it's worth saying that Mistral provides a lot of actions out of +the box (including actions for most of the core OpenStack services) and +it's also easy to plug new actions into Mistral. + +Common Task Attributes +'''''''''''''''''''''' + +All Mistral tasks regardless of workflow type have the following common +attributes: + +- **description** - Arbitrary text containing task description. + *Optional*. +- **action** - Name of the action associated with the task. *Required + but mutually exclusive with* **workflow**. +- **workflow** - Name of the workflow associated with the task. + *Mutually exclusive with* **action**. +- **input** - Actual input parameter values of the task. *Optional*. + Value of each parameter is a JSON-compliant type such as number, + string etc, dictionary or list. It can also be a YAQL expression to + retrieve value from task context or any of the mentioned types + containing inline YAQL expressions (for example, string + "{$.movie\_name} is a cool movie!") +- **publish** - Dictionary of variables to publish to the workflow + context. Any JSON-compatible data structure optionally containing + YAQL expression to select precisely what needs to be published. + Published variables will be accessible for downstream tasks via using + YAQL expressions. *Optional*. +- **policies** - Dictionary-like section defining task policies that + influence how Mistral Engine runs tasks. Policies are explained in a + separate `paragraph <#Policies>`__. *Optional*. + +Policies +'''''''' + +Any Mistral task regardless of what its workflow type can optionally +have configured policies. + +YAML example + + +| ``my_task:`` +| ``  ...`` +| ``  policies:`` +| ``    wait-before: 2`` +| ``    wait-after: 4`` +| ``    timeout: 30`` +| ``    retry:`` +| ``      count: 10`` +| ``      delay: 20`` +| ``      break-on: $.my_var = true`` + +'wait-before' + + +Defines a delay in seconds that Mistral Engine should wait before +starting a task. + +'wait-after' + + +Defines a delay in seconds that Mistral Engine should wait after a task +has completed before starting next tasks defined in 'on-success', +'on-error' or 'on-complete'. + +'timeout' + + +Defines a period of time in seconds after which a task will be failed +automatically by engine if hasn't completed. + +'retry' + + +Defines a pattern how task should be repeated in case of an error. + +- **count** - Defines a maximum number of times that a task can be + repeated. +- **delay** - Defines a delay in seconds between subsequent task + iterations. +- **break-on** - Defines a YAQL expression that will break iteration + loop if it evaluates to 'true'. If it fires then the task is + considered successful. + +Simplified Input Syntax +''''''''''''''''''''''' + +When describing a workflow task it's possible to specify its input +parameters in two ways: + +Full syntax: + +| ``my_task:`` +| ``  action: std.http`` +| ``  input:`` +| ``    url: ``\ ```http://mywebsite.org`` `__ +| ``    method: GET`` + +Simplified syntax: + +| `` my_task:`` +| ``   action: std.http url="``\ ```http://mywebsite.org`` `__\ ``" method="GET"`` + +The same rules apply to tasks associated with workflows. + +Full syntax: + +| ``my_task:`` +| ``  workflow: some_nested_workflow`` +| ``  input:`` +| ``    param1: val1`` +| ``    param2: val2`` + +Simplified syntax: + +| `` my_task:`` +| ``   workflow: some_nested_workflow param1='val1' param2='val2'`` + +**Note**: It's also possible to merge these two approaches and specify a +part of parameters using simplified key-value pairs syntax and using +keyword 'input'. In this case all the parameters will be effectively +merged. If the same parameter is specified in both ways then the one +under 'input' keyword takes precedence. + +Direct Workflow +^^^^^^^^^^^^^^^ + +Direct workflow consists of tasks combined in a graph where every next +task starts after another one depending on produced result. So direct +workflow has a notion of transition. Direct workflow is considered to be +completed if there aren't any transitions left that could be used to +jump to next tasks. + +| |Figure 1. Mistral Direct Workflow.| + + Figure 1. Mistral Direct Workflow. + +YAML example +'''''''''''' + +| ``---`` +| ``version: '2.0'`` +| ``create_vm_and_send_email:`` +| ``  type: direct`` +| ``  input:`` +| ``    - vm_name`` +| ``    - image_id`` +| ``    - flavor_id`` +| ``  output:`` +| ``    result: $.vm_id`` +| ``  tasks:`` +| ``    create_vm:`` +| ``      action: nova.servers_create name={$.vm_name} image={$.image_id} flavor={$.flavor_id}`` +| ``      publish:`` +| ``        vm_id: $.id`` +| ``      on-error:`` +| ``        - send_error_email`` +| ``      on-success:`` +| ``        - send_success_email`` +| ``    send_error_email:`` +| ``      action: send_email to='admin@mysite.org' body='Failed to create a VM'`` +| ``      on_complete:`` +| ``        - fail`` +| ``    send_success_email:`` +| ``      action: send_email to='admin@mysite.org' body='Vm is successfully created and its id: {$.vm_id}'`` + +Transitions with YAQL expressions +''''''''''''''''''''''''''''''''' + +Task transitions can be determined by success/error/completeness of the +previous tasks and also by additional YAQL guard expressions that can +access any data produced by upstream tasks. So in the example above task +'create\_vm' could also have a YAQL expression on transition to task +'send\_success\_email' as follows: + +| ``create_vm:`` +| ``  ...`` +| ``  on-success:`` +| ``    - send_success_email: $.vm_id != null`` + +And this would tell Mistral to run 'send\_success\_email' task only if +'vm\_id' variable published by task 'create\_vm' is not empty. YAQL +expressions can also be applied to 'on-error' and 'on-complete'. + +Direct Workflow Task Attributes +''''''''''''''''''''''''''''''' + +- **on-success** - List of tasks which will run after the task has + completed successfully. *Optional*. +- **on-error** - List of tasks which will run after the task has + completed with an error. *Optional*. +- **on-complete** - List of tasks which will run after the task has + completed regardless of whether it is successful or not. *Optional*. + +Reverse Workflow +^^^^^^^^^^^^^^^^ + +In reverse workflow all relationships in workflow task graph are +dependencies. In order to run this type of workflow we need to specify a +task that needs to be completed, it can be conventionally called 'target +task'. When Mistral Engine starts a workflow it recursively identifies +all the dependencies that need to be completed first. + +| |Figure 2. Mistral Reverse Workflow.| + + Figure 2. Mistral Reverse Workflow. + +Figure 2 explains how reverse workflow works. In the example, task +**T1** is chosen a target task. So when the workflow starts Mistral will +run only tasks **T7**, **T8**, **T5**, **T6**, **T2** and **T1** in the +specified order (starting from tasks that have no dependencies). Tasks +**T3** and **T4** won't be a part of this workflow because there's no +route in the directed graph from **T1** to **T3** or **T4**. + +YAML example +'''''''''''' + +| ``---`` +| ``version: '2.0'`` +| ``create_vm_and_send_email:`` +| ``  type: reverse`` +| ``  input:`` +| ``    - vm_name`` +| ``    - image_id`` +| ``    - flavor_id`` +| ``  output:`` +| ``    result: $.vm_id`` +| ``  tasks:`` +| ``    create_vm:`` +| ``      action: nova.servers_create name={$.vm_name} image={$.image_id} flavor={$.flavor_id}`` +| ``      publish:`` +| ``        vm_id: $.id`` +| ``    search_for_ip:`` +| ``      action: nova.floating_ips_findall instance_id=null`` +| ``      publish:`` +| ``        vm_ip: $[0].ip`` +| ``    associate_ip:`` +| ``      action: nova.servers_add_floating_ip server={$.vm_id} address={$.vm_ip}`` +| ``      requires: [search_for_ip]`` +| ``    send_email:`` +| ``      action: send_email to='admin@mysite.org' body='Vm is created and id {$.vm_id} and ip address {$.vm_ip}'`` +| ``      requires: [create_vm, associate_ip]`` + +Reverse Workflow Task Attributes +'''''''''''''''''''''''''''''''' + +- **requires** - List of tasks which should be executed before this + task. *Optional*. + +Actions +~~~~~~~ + +Action defines what exactly needs to be done when task starts. Action is +similar to a regular function in general purpose programming language +like Python. It has a name and parameters. Mistral distinguishes 'system +actions' and 'Ad-hoc actions'. + +System Actions +^^^^^^^^^^^^^^ + +System actions are provided by Mistral out of the box and can be used by +anyone. It is also possible to add system actions for specific Mistral +installation via a special plugin mechanism. Currently, built-in system +actions are: + +std.http +'''''''' + +Sends an HTTP request. + +Input parameters: + +- **url** - URL for the HTTP request. *Required*. +- **method** - method for the HTTP request. *Optional*. Default is + 'GET'. +- **params** - Dictionary or bytes to be sent in the query string for + the HTTP request. *Optional*. +- **body** - Dictionary, bytes, or file-like object to send in the body + of the HTTP request. *Optional*. +- **headers** - Dictionary of HTTP Headers to send with the HTTP + request. *Optional*. +- **cookies** - Dictionary of HTTP Cookies to send with the HTTP + request. *Optional*. +- **auth** - Auth to enable Basic/Digest/Custom HTTP Auth. *Optional*. +- **timeout** - Float describing the timeout of the request in seconds. + *Optional*. +- **allow\_redirects** - Boolean. Set to True if POST/PUT/DELETE + redirect following is allowed. *Optional*. +- **proxies** - Dictionary mapping protocol to the URL of the proxy. + *Optional*. + +| +| Example: + +| ``http_task:`` +| ``  action: std.http url='google.com'`` + +std.mistral\_http +''''''''''''''''' + +This actions works just like 'std.http' with the only exception: when +sending a request it inserts the following HTTP headers: + +- **Mistral-Execution-Id** - Identifier of the workflow execution this + action is associated with. +- **Mistral-Task-Id** - Identifier of the task instance this action is + associated with. + +Using this action makes it possible to do any work in asynchronous +manner triggered via HTTP protocol. That means that Mistral can send a +request using 'std.mistral\_http' and then any time later whatever +system that received this request can notify Mistral back (using its +public API) with the result of this action. Header **Mistral-Task-Id** +is required for this operation because it is used a key to find +corresponding task in Mistral to attach the result to. + +std.email +''''''''' + +Sends an email message via SMTP protocol. + +- **params** - Dictionary containing the following keys: + + - **to** - Comma separated list of recipients. *Required*. + - **subject** - Subject of the message. *Required*. + - **body** - Text containing message body. *Required*. + +- **settings** - Dictionary containing the following keys: + + - **from** - Sender email address. *Required*. + - **smtp\_server** - SMTP server host name. *Required*. + - **password** - SMTP server password. *Required*. + +| +| Example: + +| ``http_task:`` +| ``  action: std.email`` +| ``  input:`` +| ``    params:`` +| ``      to: admin@mywebsite.org`` +| ``      subject: Hello from Mistral :)`` +| ``      body: |`` +| ``        Cheers! (:_:)`` +| ``        -- Thanks, Mistral Team.`` +| ``    settings:`` +| ``      from: mistral@openstack.org`` +| ``      smtp_server: smtp.google.com`` +| ``      password: SECRET `` + +The syntax of 'std.emal' action is pretty verbose. However, it can be +significantly simplified using Ad-hoc actions. More about them +`below <#Ad-hoc_Actions>`__. + +std.ssh +''''''' + +Runs Secure Shell command. + +Input parameters: + +- **cmd** - String containing a shell command that needs to be + executed. *Required*. +- **host** - Host name that the command needs to be executed on. + *Required*. +- **username** - User name to authenticate on the host. +- **password** - User password to to authenticate on the host. + +| +| **Note**: Authentication using key pairs is currently not supported. + +std.echo +'''''''' + +Simple action mostly needed for testing purposes that returns a +predefined result. + +Input parameters: + +- **output** - Value of any type that needs to be returned as a result + of the action. *Required*. + +Ad-hoc Actions +^^^^^^^^^^^^^^ + +Ad-hoc action is a special type of action that can be created by user. +Ad-hoc action is always created as a wrapper around any other existing +system action and its main goal is to simplify using same actions many +times with similar pattern. + +**Note**: Nested ad-hoc actions currently are not supported (i.e. ad-hoc +action around another ad-hoc action). + +YAML example +'''''''''''' + +| ``---`` +| ``version: '2.0'`` +| ``error_email:`` +| ``  input:`` +| ``    - execution_id`` +| ``  base: std.email`` +| ``  base-input:`` +| ``    params:`` +| ``      to: admin@mywebsite.org`` +| ``      subject: Something went wrong with your Mistral workflow :(`` +| ``      body: |`` +| ``          Please take a look at Mistral Dashboard to find out what's wrong`` +| ``          with your workflow execution {$.execution_id}.`` +| ``          Everything's going to be alright!`` +| ``          -- Sincerely, Mistral Team.`` +| ``      settings:`` +| ``        from: mistral@openstack.org`` +| ``        smtp_server: smtp.google.com`` +| ``        password: SECRET `` + +Once this action is uploaded to Mistral any workflow will be able to use +it as follows: + +| ``my_workflow:`` +| ``  tasks:`` +| ``    ...`` +| ``    send_error_email`` +| ``      action: error_email execution_id={$.__execution.id}`` + +Attributes +'''''''''' + +- **base** - Name of base action that this action is built on top of. + *Required*. +- **base-input** - Actual input parameters provided to base action. + Look at the example above. *Optional*. +- **input** - List of declared action parameters which should be + specified as corresponding task input. This attribute is optional and + used only for documenting purposes. Mistral now does not enforce + actual input parameters to exactly correspond to this list. Based + parameters will be calculated based on provided actual parameters + with using YAQL expressions so what's used in expressions implicitly + define real input parameters. Dictionary of actual input parameters + is referenced in YAQL as '$.'. Redundant parameters will be simply + ignored. +- **output** - Any data structure defining how to calculate output of + this action based on output of base action. It can optionally have + YAQL expressions to access properties of base action output + referenced in YAQL as '$.'. + +Triggers [coming soon...] +~~~~~~~~~~~~~~~~~~~~~~~~~ + +**NOTE**: Triggers are not yet implemented as part of version 0.1, they +will go into in one of the next builds, likely 0.2 + +Using triggers it is possible to run workflows according to specific +rules: periodically setting a cron (http://en.wikipedia.org/wiki/Cron) +pattern or on external events like ceilometer alarm. + +Below are two options picturing what Mistral team is currently +discussing as a candidate for implementation: + +Option 1: + +| ``---`` +| ``version: '2.0'`` +| ``cron_trigger:`` +| ``  type: periodic`` +| ``  parameters:`` +| ``    cron-pattern: "*/1 * * * *"`` +| ``  workflows:`` +| ``    - wf1:`` +| ``      parameters:`` +| ``        # Regular dictionary (heavy syntax)`` +| ``      ...`` +| ``    - wf2 param1=val1 param2=val2 task_name='task1' # Short syntax`` +| ``  actions:`` +| ``    # The same for actions`` + +Option 2: + +| ``---`` +| ``version: '2.0'`` +| ``cron_trigger:`` +| ``  type: periodic`` +| ``  parameters:`` +| ``    cron-pattern: "*/1 * * * *"`` +| ``  workflows: ["wf2 param1=val1 param2=val2 task_name='task1'", ...] # List of workflows with using simplified syntax.`` +| ``  actions: # same for actions`` + +If you are interested in this functionality you can participate in +mailing list +`openstack-dev@lists.openstack.org `__. + +Workbooks +~~~~~~~~~ + +As mentioned before, workbooks still exist in Mistral DSL version 2 but +purely for convenience. Using workbooks users can combine multiple +entities of any type (workflows, actions and triggers) into one document +and upload to Mistral service. When uploading a workbook Mistral will +parse it and save its workflows, actions and triggers as independent +objects which will be accessible via their own API endpoints +(/workflows, /actions and /triggers/). Once it's done the workbook comes +out of the game. User can just start workflows and use references to +workflows/actions/triggers as if they were uploaded without workbook in +the first place. However, if we want to modify these individual objects +we can modify the same workbook definition and re-upload it to Mistral +(or, of course, we can do it independently). + +Namespacing +^^^^^^^^^^^ + +One thing that's worth noting is that when using a workbook Mistral uses +its name as a prefix for generating final names of workflows, actions +and triggers included into the workbook. To illustrate this principle +let's take a look at the figure below. + +| |Figure 3. Mistral Workbook Namespacing.| +| So after a workbook has been uploaded its workflows, actions and +triggers become independent objects but with slightly different names. + +YAML example +^^^^^^^^^^^^ + +| ``---`` +| ``version: '2.0'`` +| ``name: my_workbook`` +| ``description: My set of workflows and ad-hoc actions`` +| ``workflows:`` +| ``  local_workflow1:`` +| ``    type: direct`` +| ``    `` +| ``    tasks:`` +| ``      task1:`` +| ``        action: local_action str1='Hi' str2=' Mistral!'`` +| ``        on-complete:`` +| ``          - task2`` +| ``    task2:`` +| ``      action: global_action`` +| ``      ...`` +| ``    `` +| ``  local_workflow2:`` +| ``    type: reverse`` +| ``    tasks:`` +| ``      task1:`` +| ``        workflow: local_workflow1`` +| ``        on-complete:`` +| ``          - task2`` +| ``      `` +| ``      task2:`` +| ``        workflow: global_workflow param1='val1' param2='val2'`` +| ``        ...`` +| ``actions:`` +| ``  local_action:`` +| ``    input:`` +| ``      - str1`` +| ``      - str2`` +| ``    base: std.echo output="{$.str1}{$.str2}"`` + +**Note**: Even though names of objects inside workbooks change upon +uploading Mistral allows referencing between those objects using local +names declared in the original workbook. + +Attributes +^^^^^^^^^^ + +- **name** - Workbook name. *Required*. +- **description** - Workbook description. *Optional*. +- **tags** - String with arbitrary comma-separated values. + **Optional**. +- **workflows** - Dictionary containing workflow definitions. + *Optional*. +- **actions** - Dictionary containing ad-hoc action definitions. + *Optional*. +- **triggers** - Dictionary containing trigger definitions. *Optional*. + (**Currently not supported**) + +.. |Figure 1. Mistral Direct Workflow.| image:: /img/Mistral_direct_workflow.png +.. |Figure 2. Mistral Reverse Workflow.| image:: /img/Mistral_reverse_workflow.png +.. |Figure 3. Mistral Workbook Namespacing.| image:: /img/mistral_workbook_namespacing.png diff --git a/doc/source/dsl/index.rst b/doc/source/dsl/index.rst index 0efc0720..2dcc3480 100644 --- a/doc/source/dsl/index.rst +++ b/doc/source/dsl/index.rst @@ -2,7 +2,7 @@ DSL Specification ================= .. toctree:: - :maxdepth: 2 + :maxdepth: 1 DSL v2 DSL v1 (deprecated) diff --git a/doc/source/img/Mistral_direct_workflow.png b/doc/source/img/Mistral_direct_workflow.png new file mode 100644 index 0000000000000000000000000000000000000000..af77871fc7cff61e9e162d81f0f278a5be2e48d6 GIT binary patch literal 14571 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 YON(jxz>(778u+6qrz%?}Z5;H!0j$(ZF#rGn literal 0 HcmV?d00001