-
Notifications
You must be signed in to change notification settings - Fork 45
/
Copy pathorchestrate.rb
executable file
·152 lines (126 loc) · 3.5 KB
/
orchestrate.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/usr/bin/env ruby
# frozen_string_literal: true
example_description = <<DESC
Orchestrate Example
===================
This example simulates a workflow of setting up an infrastructure, using
more high-level steps in CreateInfrastructure, that expand to smaller steps
of PrepareDisk, CraeteVM etc.
It shows the possibility to run the independend actions concurrently, chaining
the actions (passing the output of PrepareDisk action to CreateVM, automatically
detecting the dependency making sure to run the one before the other).
It also simulates a failure and demonstrates the Dynflow ability to rescue
from the error and consinue with the run.
Once the Sinatra web console starts, you can navigate to #{ExampleHelper::DYNFLOW_URL}
to see what's happening in the Dynflow world.
DESC
require_relative 'example_helper'
module Orchestrate
class CreateInfrastructure < Dynflow::Action
def plan
sequence do
concurrence do
plan_action(CreateMachine, 'host1', 'db')
plan_action(CreateMachine, 'host2', 'storage')
end
plan_action(CreateMachine,
'host3',
'web_server',
:db_machine => 'host1',
:storage_machine => 'host2')
end
end
end
class CreateMachine < Dynflow::Action
def plan(name, profile, config_options = {})
prepare_disk = plan_action(PrepareDisk, 'name' => name)
create_vm = plan_action(CreateVM,
:name => name,
:disk => prepare_disk.output['path'])
plan_action(AddIPtoHosts, :name => name, :ip => create_vm.output[:ip])
plan_action(ConfigureMachine,
:ip => create_vm.output[:ip],
:profile => profile,
:config_options => config_options)
plan_self(:name => name)
end
def finalize
# this is called after run methods of the actions in the
# execution plan were finished
end
end
class Base < Dynflow::Action
def sleep!
sleep(rand(2))
end
end
class PrepareDisk < Base
def queue
:slow
end
input_format do
param :name
end
output_format do
param :path
end
def run
sleep!
output[:path] = "/var/images/#{input[:name]}.img"
end
end
class CreateVM < Base
input_format do
param :name
param :disk
end
output_format do
param :ip
end
def run
sleep!
output[:ip] = "192.168.100.#{rand(256)}"
end
end
class AddIPtoHosts < Base
input_format do
param :ip
end
def run
sleep!
end
end
class ConfigureMachine < Base
input_format do
param :ip
param :profile
param :config_options
end
def run
# for demonstration of resuming after error
if ExampleHelper.something_should_fail?
ExampleHelper.nothing_should_fail!
puts <<-MSG.gsub(/^.*\|/, '')
| Execution plan #{execution_plan_id} is failing
| You can resume it at #{ExampleHelper::DYNFLOW_URL}/#{execution_plan_id}
MSG
raise "temporary unavailabe"
end
sleep!
end
end
end
if $0 == __FILE__
world = ExampleHelper.create_world
ExampleHelper.set_world(world)
ExampleHelper.world.action_logger.level = Logger::INFO
ExampleHelper.something_should_fail!
ExampleHelper.world.trigger(Orchestrate::CreateInfrastructure)
Thread.new do
9.times do
ExampleHelper.world.trigger(Orchestrate::CreateInfrastructure)
end
end
puts example_description
ExampleHelper.run_web_console
end