Heat Mistral resources usage examples

Creating resources using Heat template and check that they are available in Mistral service.
This case means creating stack with one Mistral Workflow resource, which allows to create nova server. After creating stack workflow can be executed. Workflow execution in Heat means sending signal to workflow resource with, perhaps, some data. This case checks workflow execution with and without data.

Create Mistral workflow resource using Heat OS::Mistral::Workflow
heat_template_version: 2013-05-23 parameters: image: type: string flavor: type: string default: 2 name: type: string default: mistral-test resources: create_vm: type: OS::Mistral::Workflow properties: type: direct input: name: { get_param: name } image: { get_param: image } flavor: { get_param: flavor } output: vm_id: <% $.vm_id %> tasks: - name: create_server action: nova.servers_create name=<% $.name %> image=<% $.image %> flavor=<% $.flavor %> publish: vm_id: <% $.create_server.id %> on_success: - check_server_exists - name: check_server_exists action: nova.servers_get server=<% $.vm_id %> publish: server_exists: True on_success: - wait_instance - name: wait_instance action: nova.servers_find id=<% $.vm_id %> status='ACTIVE' policies: retry: delay: 5 count: 15 outputs: executions: value: { get_attr: [create_vm, executions] } data: value: { get_attr: [create_vm, data] }

Create stack
heat stack-create test -f template.yaml -P image=31d8eeaf-686e-4e95-bb27-765014b9f20b

Execute workflow using command heat resource-signal
heat resource-signal test create_vm mistral execution-list nova list

Execute workflow using resource-signal with non-default workflow input
heat resource-signal test create_vm -D '{"input": {"image": "6e8ee0ce-1a53-4dc7-a97e-6332badbb3fa"}}' mistral execution-list

Check stack outputs
heat stack-show test

|                      |   {                                                                                         |                       |     "output_value": { |                      |         "input": { |                      |             "image": "31d8eeaf-686e-4e95-bb27-765014b9f20b", |                      |             "name": "mistral-test", |                      |             "flavor": 2 |                      |         },                                                                  |                       |         "name": "test-create_vm-6mk5u42i4dqa" |                      |     },                                                                      |                       |     "description": "No description given", |                      |     "output_key": "data" |                      |   },                                                             |                       |   {                                                              |                       |     "output_value": [ |                      |         {                                                       |                       |             "workflow_name": "test-create_vm-6mk5u42i4dqa", |                      |             "created_at": "2015-02-16 13:08:23", |                      |             "updated_at": "2015-02-16 13:08:45", |                      |             "state": "SUCCESS", |                      |             "input": { |                      |                 "image": "6e8ee0ce-1a53-4dc7-a97e-6332badbb3fa", |                      |                 "name": "mistral-test", |                      |                 "flavor": 2 |                      |             },                                                                                         |                       |             "output": { |                      |                 "vm_id": "d7f33c8e-6855-4d17-a39b-325323f6eaee" |                      |             },                                                                                        |                       |             "id": "f67c611c-adf7-4ad6-b5ab-27cc5fe79c34" |                      |         },                                                                                            |                       |         {                                                                                             |                       |             "workflow_name": "test-create_vm-6mk5u42i4dqa", |                      |             "created_at": "2015-02-16 13:01:37", |                      |             "updated_at": "2015-02-16 13:02:01", |                      |             "state": "SUCCESS", |                      |             "input": { |                      |                 "image": "31d8eeaf-686e-4e95-bb27-765014b9f20b", |                      |                 "name": "mistral-test", |                      |                 "flavor": 2 |                      |             },                                                                                         |                       |             "output": { |                      |                 "vm_id": "853d9117-d4e1-4454-a066-ec3dd5863193" |                      |             },                                                                                         |                       |             "id": "2cc27206-ee42-44ca-bf30-1907f90709e4" |                      |         }                                                                                              |                       |     ],                                                                                                 |                       |     "description": "No description given", |                      |     "output_key": "executions" |                      |   }                                                                    |                       | ]

Using Ceilometer Alarm with Mistral workflow in Heat.
In this case stack creates with Mistral workflow, which allows to create nova server, and Ceilometer alarm, which send signal to execute workflow. After stack creation alarm get state 'alarm' and sends signal to workflow resource. It executed and creates nova server.

Create Heat template (template.yaml) which uses Mistral workflow and Ceilometer alarm resources
heat_template_version: 2013-05-23 resources: workflow: type: OS::Mistral::Workflow properties: type: direct tasks: - name: alarm action: std.echo output='alarm!' publish: state: 'alarm!' alarm: type: OS::Ceilometer::Alarm properties: meter_name: instance statistic: count period: 60 evaluation_periods: 1 threshold: 100 alarm_actions: - {get_attr: [workflow, alarm_url] } comparison_operator: lt

Create Heat stack using template template.yaml
heat stack-create test -f heat-templates/mistral-and-ceilometer.yaml mistral workflow-list ceilometer alarm-list

Wait until Ceilometer alarm get state 'alarm'
ceilometer alarm-list mistral execution-list

Check execution output (it must equals 'alarm!')
mistral execution-get-output 85cff77d-3da5-423b-a4ca-fb8be4a9ce2f ... "state": "alarm!", "alarm": { "state": "alarm!" }, ...

Testing autoscaling using Mistral resources.
This case shows how to use mistral resources for autoscale testing. In this stack workflows are used to get ip of the server and to load/release cpu and triggers allow to execute these workflows (every 10 minutes by default).

Create template heat_autoscaling_nova.yaml with Mistral resources, Ceilometer alarms and Heat autoscaling group
heat_template_version: 2014-10-16 parameters: InstanceType: type: string default: m1.heat ImageId: type: string default: cirros-0.3.2-x86_64-uec User: type: string default: cirros Password: type: string default: 'cubswin:)'   Pattern_release:      type: string      default: "0,20,40 * * * *"      description: Time to execute workflow wf_release_cpu    Pattern_load:      type: string      default: "10,30,50 * * * *"      description: Time to execute workflow wf_load_cpu  resources:    my_asg:      type: OS::Heat::AutoScalingGroup      properties:      resource:        type: server_with_ip.yaml        properties:          image: { get_param: ImageId }          flavor: { get_param: InstanceType }          security_group: {get_resource: security_group}          metadata: {"metering.stack": {get_param: "OS::stack_id"}}          min_size: 1          max_size: 2    scale_up_policy:      type: OS::Heat::ScalingPolicy      properties:        adjustment_type: change_in_capacity        auto_scaling_group_id: {get_resource: my_asg}        cooldown: 60        scaling_adjustment: 1    scale_down_policy: type: OS::Heat::ScalingPolicy properties: adjustment_type: change_in_capacity auto_scaling_group_id: {get_resource: my_asg} cooldown: 60 scaling_adjustment: '-1' cpu_alarm_high: type: OS::Ceilometer::Alarm properties: description: Scale-up if the average CPU > 50% for 1 minute meter_name: cpu_util statistic: avg period: 60 evaluation_periods: 1 threshold: 50 alarm_actions: - {get_attr: [scale_up_policy, alarm_url]} matching_metadata: {'metadata.user_metadata.stack': {get_param: "OS::stack_id"}} comparison_operator: gt   cpu_alarm_low: type: OS::Ceilometer::Alarm properties: description: Scale-down if the average CPU < 15% for 1 minutes meter_name: cpu_util statistic: avg period: 60 evaluation_periods: 1 threshold: 15 alarm_actions: - {get_attr: [scale_down_policy, alarm_url]} matching_metadata: {'metadata.user_metadata.stack': {get_param: "OS::stack_id"}} comparison_operator: lt   security_group: type: AWS::EC2::SecurityGroup properties: GroupDescription: 'Enable SSH access' SecurityGroupIngress: - IpProtocol: 'tcp' FromPort: '22' ToPort : '22' CidrIp : '0.0.0.0/0' wf_load_cpu: type: OS::Mistral::Workflow properties: type: direct tasks: - name: get_output action: heat.stacks_get stack_id=<% $.stack_id %> publish: vm_ip: <% $.get_output._info.outputs[0].output_value %> on_success: - run_ssh - name: run_ssh action: std.ssh cmd='cat /dev/urandom | gzip -9 > /dev/null &' host=<% $.vm_ip %> username=<% $.user %> password=<% $.password %> input: {'user': {get_param: User}, 'password': {get_param: Password}, 'stack_id': {get_param: "OS::stack_id"}} wf_release_cpu: type: OS::Mistral::Workflow properties: type: direct tasks: - name: get_output action: heat.stacks_get stack_id=<% $.stack_id %> publish: vm_ip: <% $.get_output._info.outputs[0].output_value %> on_success: - run_ssh - name: run_ssh action: std.ssh cmd="kill -9 $(ps aux | grep 'cat /dev/urandom' | awk '{print $1}')" host=<% $.vm_ip %> username=<% $.user %> password=<% $.password %> input: {'user': {get_param: User}, 'password': {get_param: Password}, 'stack_id': {get_param: "OS::stack_id"}} trigger_load_cpu: type: OS::Mistral::CronTrigger properties: pattern: {get_param: Pattern_load} workflow: {get_attr: [wf_load_cpu, data]} trigger_release_cpu: type: OS::Mistral::CronTrigger properties: pattern: {get_param: Pattern_release} workflow: {get_attr: [wf_release_cpu, data]} outputs: ip: value: {'Fn::Select': ['0', {get_attr: [my_asg, outputs_list, ip]}]}

Create template server_with_ip.yaml for nested stack
heat_template_version: 2013-05-23 parameters: image: type: string flavor: type: string security_group: type: string metadata: type: json resources: server: type: OS::Nova::Server properties: flavor: {get_param: flavor} image: {get_param: image} metadata: {get_param: metadata} security_groups: - get_param: security_group floating_ip: type: OS::Nova::FloatingIP floating_ip_association: type: OS::Nova::FloatingIPAssociation properties: floating_ip: {get_resource: floating_ip} server_id: {get_resource: server} outputs: ip: value: {get_attr: [floating_ip, ip]} server_id: value: {get_resource: server}

Create stack
heat stack-create test-asg -f heat_autoscaling_nova.yaml

Check that resources were created
heat stack-list nova list ceilometer alarm-list mistral workflow-list mistral cron-trigger-list

Wait for 10:50 (next execution time of trigger_load_cpu) and check again
ceilometer alarm-list nova list

Wait for 11:00 (next execution time of trigger_release_cpu)
ceilometer alarm-list nova list

Mistral Workflow resource using property name
This template create stack with Workflow resource named stack_name-workflow-test_workflow.

heat_template_version: 2013-05-23 resources: workflow: type: OS::Mistral::Workflow properties: type: direct name: test_workflow description: Just testing workflow resource. input: phrase: Hello! output: out: <% $.word %> tasks: - name: hello action: std.echo output=<% $.phrase %> publish: word: <% $.hello %> outputs: exec: value: { get_attr: [workflow, executions] }

Two Mistral Workflows with referencing by intrinsic function get_resource
This template create stack with two Workflow resources, one of them references to another by intrinsic function get_resource.

heat_template_version: 2013-05-23 resources: wf1: type: OS::Mistral::Workflow properties: type: direct tasks: - name: hello! action: std.noop wf2: type: OS::Mistral::Workflow properties: type: direct tasks: - name: call workflow: { get_resource: wf1 } outputs: name: value: {get_attr: [wf2, data]}

Reverse-type Mistral Workflow
This template shows how to use reverse-type Workflows. If you want to execute this Workflow, you need to provide param task_name in resourse signal data, i.e.:

heat resource_signal test_stack create_vm -D '{"params": {"task_name": "create_vm"}}'

Template: heat_template_version: 2013-05-23 parameters: image_id: type: string flavor: type: string default: 2 resources: create_vm: type: OS::Mistral::Workflow properties: type: reverse input: vm_name: test image_id: { get_param: image_id } flavor_id: { get_param: flavor } output: result: <% $.vm_id %> tasks: - name: create_vm action: nova.servers_create name=<% $.vm_name %> image=<% $.image_id %> flavor=<% $.flavor_id %> publish: vm_id: <% $.create_vm.id %> - name: search_for_ip action: nova.floating_ips_findall instance_id=null publish: vm_ip: <% $.search_for_ip[0].ip %> - name: associate_ip action: nova.servers_add_floating_ip server=<% $.vm_id %> address=<% $.vm_ip %> requires: - search_for_ip - name: send_email action: std.noop publish: vm_id: <% $.vm_id %> vm_ip: <% $.vm_ip %> requires: [create_vm, associate_ip]