Add documentation - part 2
Migrate DSL specs from wiki Coming up next: setup autodocs to for REST v2 Change-Id: I6df52adcbf0f22d506c3c08e48318f0a9a6f60fe
This commit is contained in:
parent
e328238c4c
commit
460f5d691b
@ -1,2 +1,404 @@
|
||||
DSL v1 (deprecated)
|
||||
===================
|
||||
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://`` <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"``
|
||||
| `` }``
|
||||
| `` }``
|
||||
|
@ -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`` <http://mywebsite.org>`__
|
||||
| `` method: GET``
|
||||
|
||||
Simplified syntax:
|
||||
|
||||
| `` my_task:``
|
||||
| `` action: std.http url="``\ ```http://mywebsite.org`` <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 <mailto:openstack-dev@lists.openstack.org?subject=%5Bopenstack-dev%5D%5Bmistral%5D>`__.
|
||||
|
||||
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
|
||||
|
@ -2,7 +2,7 @@ DSL Specification
|
||||
=================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
|
||||
DSL v2 <dsl_v2>
|
||||
DSL v1 (deprecated) <dsl_v1>
|
||||
|
BIN
doc/source/img/Mistral_direct_workflow.png
Normal file
BIN
doc/source/img/Mistral_direct_workflow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
doc/source/img/Mistral_reverse_workflow.png
Normal file
BIN
doc/source/img/Mistral_reverse_workflow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
doc/source/img/Mistral_workbook_namespacing.png
Normal file
BIN
doc/source/img/Mistral_workbook_namespacing.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
Loading…
Reference in New Issue
Block a user