wakame 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +20 -0
- data/README.rdoc +63 -0
- data/Rakefile +86 -0
- data/VERSION +1 -0
- data/app_generators/wakame/templates/README +0 -0
- data/app_generators/wakame/templates/Rakefile +18 -0
- data/app_generators/wakame/templates/bin/wakame-agent +9 -0
- data/app_generators/wakame/templates/bin/wakame-master +9 -0
- data/app_generators/wakame/templates/bin/wakameadm +9 -0
- data/app_generators/wakame/templates/cluster/resources/apache_app/apache_app.rb +54 -0
- data/app_generators/wakame/templates/cluster/resources/apache_app/conf/apache2.conf +46 -0
- data/app_generators/wakame/templates/cluster/resources/apache_app/conf/envvars-app +7 -0
- data/app_generators/wakame/templates/cluster/resources/apache_app/conf/sites-app.conf +23 -0
- data/app_generators/wakame/templates/cluster/resources/apache_app/conf/system-app.conf +67 -0
- data/app_generators/wakame/templates/cluster/resources/apache_app/init.d/apache2-app +192 -0
- data/app_generators/wakame/templates/cluster/resources/apache_lb/apache_lb.rb +56 -0
- data/app_generators/wakame/templates/cluster/resources/apache_lb/conf/apache2.conf +46 -0
- data/app_generators/wakame/templates/cluster/resources/apache_lb/conf/envvars-lb +6 -0
- data/app_generators/wakame/templates/cluster/resources/apache_lb/conf/sites-lb.conf +54 -0
- data/app_generators/wakame/templates/cluster/resources/apache_lb/conf/system-lb.conf +75 -0
- data/app_generators/wakame/templates/cluster/resources/apache_lb/init.d/apache2-lb +192 -0
- data/app_generators/wakame/templates/cluster/resources/apache_www/apache_www.rb +50 -0
- data/app_generators/wakame/templates/cluster/resources/apache_www/conf/apache2.conf +47 -0
- data/app_generators/wakame/templates/cluster/resources/apache_www/conf/envvars-www +7 -0
- data/app_generators/wakame/templates/cluster/resources/apache_www/conf/sites-www.conf +23 -0
- data/app_generators/wakame/templates/cluster/resources/apache_www/conf/system-www.conf +63 -0
- data/app_generators/wakame/templates/cluster/resources/apache_www/init.d/apache2-www +192 -0
- data/app_generators/wakame/templates/cluster/resources/ec2_elastic_ip/ec2_elastic_ip.rb +39 -0
- data/app_generators/wakame/templates/cluster/resources/mysql_master/conf/my.cnf +154 -0
- data/app_generators/wakame/templates/cluster/resources/mysql_master/init.d/mysql +185 -0
- data/app_generators/wakame/templates/cluster/resources/mysql_master/mysql_master.rb +174 -0
- data/app_generators/wakame/templates/config/boot.rb +85 -0
- data/app_generators/wakame/templates/config/cluster.rb +64 -0
- data/app_generators/wakame/templates/config/environments/common.rb +0 -0
- data/app_generators/wakame/templates/config/environments/ec2.rb +3 -0
- data/app_generators/wakame/templates/config/environments/stand_alone.rb +0 -0
- data/app_generators/wakame/templates/config/init.d/wakame-agent +72 -0
- data/app_generators/wakame/templates/config/init.d/wakame-master +73 -0
- data/app_generators/wakame/wakame_generator.rb +124 -0
- data/bin/wakame +18 -0
- data/contrib/imagesetup.sh +77 -0
- data/lib/ext/eventmachine.rb +86 -0
- data/lib/ext/shellwords.rb +172 -0
- data/lib/ext/uri.rb +15 -0
- data/lib/wakame/action.rb +156 -0
- data/lib/wakame/actions/destroy_instances.rb +39 -0
- data/lib/wakame/actions/launch_cluster.rb +31 -0
- data/lib/wakame/actions/migrate_service.rb +65 -0
- data/lib/wakame/actions/propagate_instances.rb +95 -0
- data/lib/wakame/actions/reload_service.rb +21 -0
- data/lib/wakame/actions/scaleout_when_high_load.rb +44 -0
- data/lib/wakame/actions/shutdown_cluster.rb +22 -0
- data/lib/wakame/actions/shutdown_vm.rb +19 -0
- data/lib/wakame/actions/start_service.rb +64 -0
- data/lib/wakame/actions/stop_service.rb +49 -0
- data/lib/wakame/actions/util.rb +71 -0
- data/lib/wakame/actor/daemon.rb +37 -0
- data/lib/wakame/actor/service_monitor.rb +21 -0
- data/lib/wakame/actor/system.rb +46 -0
- data/lib/wakame/actor.rb +33 -0
- data/lib/wakame/agent.rb +226 -0
- data/lib/wakame/amqp_client.rb +219 -0
- data/lib/wakame/command/action_status.rb +62 -0
- data/lib/wakame/command/actor.rb +23 -0
- data/lib/wakame/command/clone_service.rb +12 -0
- data/lib/wakame/command/launch_cluster.rb +15 -0
- data/lib/wakame/command/migrate_service.rb +21 -0
- data/lib/wakame/command/propagate_service.rb +24 -0
- data/lib/wakame/command/shutdown_cluster.rb +15 -0
- data/lib/wakame/command/status.rb +81 -0
- data/lib/wakame/command.rb +31 -0
- data/lib/wakame/command_queue.rb +44 -0
- data/lib/wakame/configuration.rb +93 -0
- data/lib/wakame/daemonize.rb +96 -0
- data/lib/wakame/event.rb +232 -0
- data/lib/wakame/event_dispatcher.rb +154 -0
- data/lib/wakame/graph.rb +79 -0
- data/lib/wakame/initializer.rb +162 -0
- data/lib/wakame/instance_counter.rb +78 -0
- data/lib/wakame/logger.rb +12 -0
- data/lib/wakame/manager/commands.rb +134 -0
- data/lib/wakame/master.rb +369 -0
- data/lib/wakame/monitor/agent.rb +50 -0
- data/lib/wakame/monitor/service.rb +183 -0
- data/lib/wakame/monitor.rb +69 -0
- data/lib/wakame/packets.rb +160 -0
- data/lib/wakame/queue_declare.rb +14 -0
- data/lib/wakame/rule.rb +116 -0
- data/lib/wakame/rule_engine.rb +202 -0
- data/lib/wakame/runner/administrator_command.rb +112 -0
- data/lib/wakame/runner/agent.rb +81 -0
- data/lib/wakame/runner/master.rb +93 -0
- data/lib/wakame/scheduler.rb +251 -0
- data/lib/wakame/service.rb +914 -0
- data/lib/wakame/template.rb +189 -0
- data/lib/wakame/trigger.rb +66 -0
- data/lib/wakame/triggers/instance_count_update.rb +45 -0
- data/lib/wakame/triggers/load_history.rb +107 -0
- data/lib/wakame/triggers/maintain_ssh_known_hosts.rb +43 -0
- data/lib/wakame/triggers/process_command.rb +34 -0
- data/lib/wakame/triggers/shutdown_unused_vm.rb +16 -0
- data/lib/wakame/util.rb +569 -0
- data/lib/wakame/vm_manipulator.rb +186 -0
- data/lib/wakame.rb +59 -0
- data/tasks/ec2.rake +127 -0
- data/tests/cluster.json +3 -0
- data/tests/conf/a +1 -0
- data/tests/conf/b +1 -0
- data/tests/conf/c +1 -0
- data/tests/setup_agent.rb +39 -0
- data/tests/setup_master.rb +28 -0
- data/tests/test_actor.rb +54 -0
- data/tests/test_agent.rb +218 -0
- data/tests/test_amqp_client.rb +94 -0
- data/tests/test_graph.rb +36 -0
- data/tests/test_master.rb +167 -0
- data/tests/test_monitor.rb +47 -0
- data/tests/test_rule_engine.rb +127 -0
- data/tests/test_scheduler.rb +123 -0
- data/tests/test_service.rb +60 -0
- data/tests/test_template.rb +67 -0
- data/tests/test_uri_amqp.rb +19 -0
- data/tests/test_util.rb +71 -0
- data/wakame_generators/resource/resource_generator.rb +54 -0
- data/wakame_generators/resource/templates/apache_app/apache_app.rb +60 -0
- data/wakame_generators/resource/templates/apache_app/conf/apache2.conf +46 -0
- data/wakame_generators/resource/templates/apache_app/conf/envvars-app +7 -0
- data/wakame_generators/resource/templates/apache_app/conf/sites-app.conf +23 -0
- data/wakame_generators/resource/templates/apache_app/conf/system-app.conf +67 -0
- data/wakame_generators/resource/templates/apache_app/init.d/apache2-app +192 -0
- data/wakame_generators/resource/templates/apache_lb/apache_lb.rb +67 -0
- data/wakame_generators/resource/templates/apache_lb/conf/apache2.conf +46 -0
- data/wakame_generators/resource/templates/apache_lb/conf/envvars-lb +6 -0
- data/wakame_generators/resource/templates/apache_lb/conf/sites-lb.conf +54 -0
- data/wakame_generators/resource/templates/apache_lb/conf/system-lb.conf +75 -0
- data/wakame_generators/resource/templates/apache_lb/init.d/apache2-lb +192 -0
- data/wakame_generators/resource/templates/apache_www/apache_www.rb +56 -0
- data/wakame_generators/resource/templates/apache_www/conf/apache2.conf +47 -0
- data/wakame_generators/resource/templates/apache_www/conf/envvars-www +7 -0
- data/wakame_generators/resource/templates/apache_www/conf/sites-www.conf +23 -0
- data/wakame_generators/resource/templates/apache_www/conf/system-www.conf +63 -0
- data/wakame_generators/resource/templates/apache_www/init.d/apache2-www +192 -0
- data/wakame_generators/resource/templates/ec2_elastic_ip/ec2_elastic_ip.rb +39 -0
- data/wakame_generators/resource/templates/mysql_master/conf/my.cnf +154 -0
- data/wakame_generators/resource/templates/mysql_master/init.d/mysql +185 -0
- data/wakame_generators/resource/templates/mysql_master/mysql_master.rb +119 -0
- metadata +289 -0
@@ -0,0 +1,160 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'wakame/agent'
|
4
|
+
require 'wakame/util'
|
5
|
+
|
6
|
+
module Wakame
|
7
|
+
module Packets
|
8
|
+
VERSION='0.4'
|
9
|
+
|
10
|
+
class ResponseBase
|
11
|
+
include AttributeHelper
|
12
|
+
|
13
|
+
attr_reader :agent_id, :responded_at
|
14
|
+
|
15
|
+
def initialize(agent)
|
16
|
+
raise TypeError unless agent.respond_to?(:agent_id)
|
17
|
+
|
18
|
+
@agent_id = agent.agent_id.to_s
|
19
|
+
@responded_at = Time.now
|
20
|
+
end
|
21
|
+
protected :initialize
|
22
|
+
|
23
|
+
def marshal
|
24
|
+
dump_attrs.inspect
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
class RequestBase
|
30
|
+
include AttributeHelper
|
31
|
+
|
32
|
+
attr_reader :token, :requested_at
|
33
|
+
|
34
|
+
def initialize(token=nil)
|
35
|
+
@token = token || Util.gen_id
|
36
|
+
@requested_at = Time.now
|
37
|
+
end
|
38
|
+
protected :initialize
|
39
|
+
|
40
|
+
def marshal
|
41
|
+
dump_attrs.inspect
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class Ping < ResponseBase
|
46
|
+
attr_reader :attrs, :monitors, :actors, :services
|
47
|
+
def initialize(agent, attrs, actors, monitors, services)
|
48
|
+
super(agent)
|
49
|
+
@attrs = attrs
|
50
|
+
@actors = actors
|
51
|
+
@monitors = monitors
|
52
|
+
@services = services
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
class Register < ResponseBase
|
58
|
+
attr_reader :root_path
|
59
|
+
def initialize(agent, root_path)
|
60
|
+
super(agent)
|
61
|
+
@root_path = root_path
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class UnRegister < ResponseBase
|
66
|
+
def initialize(agent)
|
67
|
+
super(agent)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class MonitoringStarted < ResponseBase
|
72
|
+
attr_reader :svc_id
|
73
|
+
def initialize(agent, svc_id)
|
74
|
+
super(agent)
|
75
|
+
@svc_id = svc_id
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class MonitoringStopped < ResponseBase
|
80
|
+
attr_reader :svc_id
|
81
|
+
def initialize(agent, svc_id)
|
82
|
+
super(agent)
|
83
|
+
@svc_id = svc_id
|
84
|
+
end
|
85
|
+
end
|
86
|
+
class MonitoringOutput < ResponseBase
|
87
|
+
attr_reader :svc_id, :outputs
|
88
|
+
def initialize(agent, svc_id, outputs)
|
89
|
+
super(agent)
|
90
|
+
@svc_id = svc_id
|
91
|
+
@outputs = outputs
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class EventResponse < ResponseBase
|
96
|
+
attr_reader :event
|
97
|
+
def initialize(agent, event)
|
98
|
+
super(agent)
|
99
|
+
@event = event
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class Nop < RequestBase
|
104
|
+
end
|
105
|
+
|
106
|
+
# class ServiceStart < RequestBase
|
107
|
+
# attr_reader :instance_id, :property
|
108
|
+
# def initialize(instance_id, property)
|
109
|
+
# @instance_id = instance_id
|
110
|
+
# @property = property
|
111
|
+
# end
|
112
|
+
# end
|
113
|
+
|
114
|
+
# class ServiceStop < RequestBase
|
115
|
+
# attr_reader :instance_id
|
116
|
+
# def initialize(instance_id)
|
117
|
+
# @instance_id = instance_id
|
118
|
+
# end
|
119
|
+
# end
|
120
|
+
|
121
|
+
# class ServiceReload < RequestBase
|
122
|
+
# attr_reader :instance_id
|
123
|
+
# def initialize(instance_id)
|
124
|
+
# @instance_id = instance_id
|
125
|
+
# end
|
126
|
+
# end
|
127
|
+
|
128
|
+
class ServiceStatusChanged < ResponseBase
|
129
|
+
attr_accessor :svc_id, :prev_status, :new_status, :fail_message
|
130
|
+
def initialize(agent, svc_id, prev_status, new_status, fail_message=nil)
|
131
|
+
super(agent)
|
132
|
+
@svc_id = svc_id
|
133
|
+
@prev_status = prev_status
|
134
|
+
@new_status = new_status
|
135
|
+
@fail_message = fail_message
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class ActorRequest < RequestBase
|
140
|
+
attr_reader :agent_id, :token, :path, :args
|
141
|
+
def initialize(agent_id, token, path, *args)
|
142
|
+
super()
|
143
|
+
@agent_id = agent_id
|
144
|
+
@token = token
|
145
|
+
@path = path
|
146
|
+
@args = args
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class ActorResponse < ResponseBase
|
151
|
+
attr_reader :agent_id, :token, :status
|
152
|
+
def initialize(agent, token, status)
|
153
|
+
super(agent)
|
154
|
+
@token = token
|
155
|
+
@status = status
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Wakame
|
4
|
+
module QueueDeclare
|
5
|
+
def self.included(klass)
|
6
|
+
klass.class_eval {
|
7
|
+
define_exchange 'registry', :fanout
|
8
|
+
define_exchange 'ping', :fanout
|
9
|
+
define_exchange 'agent_command', :topic
|
10
|
+
define_exchange 'agent_event', :fanout
|
11
|
+
}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/wakame/rule.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
|
2
|
+
require 'thread'
|
3
|
+
require 'forwardable'
|
4
|
+
require 'timeout'
|
5
|
+
|
6
|
+
require 'wakame/util'
|
7
|
+
|
8
|
+
module Wakame
|
9
|
+
module Rule
|
10
|
+
module BasicActionSet
|
11
|
+
class Lock
|
12
|
+
def initialize
|
13
|
+
@mutex = Mutex.new
|
14
|
+
@cond = ConditionVariable.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def signal
|
18
|
+
@mutex.synchronize {
|
19
|
+
@cond.signal
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def wait(&blk)
|
24
|
+
if blk.nil?
|
25
|
+
i=0
|
26
|
+
blk = proc {
|
27
|
+
i += 1
|
28
|
+
i > 1 ? true : false
|
29
|
+
}
|
30
|
+
end
|
31
|
+
@mutex.synchronize {
|
32
|
+
@cond.wait(@mutex) while blk.call
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class MockLock < Lock
|
38
|
+
def signal
|
39
|
+
end
|
40
|
+
|
41
|
+
def wait(&blk)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def wait_lock
|
47
|
+
Lock.new
|
48
|
+
end
|
49
|
+
|
50
|
+
def start_instance(image_id, attr={})
|
51
|
+
Wakame.log.debug("#{self.class} called start_instance(#{image_id})")
|
52
|
+
|
53
|
+
attr[:user_data] = "node=agent\namqp_server=amqp://#{master.attr[:local_ipv4]}/"
|
54
|
+
Wakame.log.debug("user_data: #{attr[:user_data]}")
|
55
|
+
vm_manipulator = VmManipulator.create
|
56
|
+
res = vm_manipulator.start_instance(image_id, attr)
|
57
|
+
inst_id = res[:instance_id]
|
58
|
+
|
59
|
+
wait_condition { | cond |
|
60
|
+
cond.wait_event(Event::AgentMonitored) { |event|
|
61
|
+
event.agent.attr[:instance_id] == inst_id
|
62
|
+
}
|
63
|
+
|
64
|
+
cond.poll(5, 100) {
|
65
|
+
vm_manipulator.check_status(inst_id, :online)
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
inst_id
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.deploy_configuration(service_instance)
|
73
|
+
Wakame.log.debug("Begin: #{self}.deploy_configuration(#{service_instance.property.class})")
|
74
|
+
|
75
|
+
begin
|
76
|
+
tmpl = Wakame::Template.new(service_instance)
|
77
|
+
tmpl.render_config
|
78
|
+
|
79
|
+
agent = service_instance.agent
|
80
|
+
src_path = tmpl.tmp_basedir.dup
|
81
|
+
src_path.sub!('/$', '') if File.directory? src_path
|
82
|
+
|
83
|
+
dest_path = File.expand_path("tmp/config/" + File.basename(tmpl.basedir), service_instance.agent.root_path)
|
84
|
+
Util.exec("rsync -e 'ssh -i #{Wakame.config.ssh_private_key} -o \"UserKnownHostsFile #{Wakame.config.ssh_known_hosts}\"' -au #{src_path}/ root@#{agent.agent_ip}:#{dest_path}")
|
85
|
+
#Util.exec("rsync -au #{src_path}/ #{dest_path}")
|
86
|
+
|
87
|
+
ensure
|
88
|
+
tmpl.cleanup if tmpl
|
89
|
+
end
|
90
|
+
|
91
|
+
Wakame.log.debug("End: #{self}.deploy_configuration(#{service_instance.property.class})")
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_agent_candidate(svc_prop, agent)
|
95
|
+
return false if agent.has_service_type?(svc_prop.class)
|
96
|
+
svc_prop.vm_spec.current.satisfy?(agent)
|
97
|
+
end
|
98
|
+
# Arrange an agent for the paticular service instance from agent pool.
|
99
|
+
def arrange_agent(svc_prop)
|
100
|
+
agent = nil
|
101
|
+
agent_monitor.each_online { |ag|
|
102
|
+
if test_agent_candidate(svc_prop, ag)
|
103
|
+
agent = ag
|
104
|
+
break
|
105
|
+
end
|
106
|
+
}
|
107
|
+
agent = agent[1] if agent
|
108
|
+
|
109
|
+
agent
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
|
2
|
+
require 'timeout'
|
3
|
+
|
4
|
+
module Wakame
|
5
|
+
class CancelActionError < StandardError; end
|
6
|
+
class CancelBroadcast < StandardError; end
|
7
|
+
class GlobalLockError < StandardError; end
|
8
|
+
|
9
|
+
class RuleEngine
|
10
|
+
|
11
|
+
FORWARD_ATTRS=[:command_queue, :agent_monitor, :service_cluster, :master]
|
12
|
+
|
13
|
+
attr_reader :triggers, :active_jobs
|
14
|
+
|
15
|
+
def master
|
16
|
+
service_cluster.master
|
17
|
+
end
|
18
|
+
|
19
|
+
def command_queue
|
20
|
+
master.command_queue
|
21
|
+
end
|
22
|
+
|
23
|
+
def agent_monitor
|
24
|
+
master.agent_monitor
|
25
|
+
end
|
26
|
+
|
27
|
+
def service_cluster
|
28
|
+
@service_cluster
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize(service_cluster, &blk)
|
32
|
+
@service_cluster = service_cluster
|
33
|
+
@triggers = []
|
34
|
+
|
35
|
+
@active_jobs = {}
|
36
|
+
@job_history = []
|
37
|
+
@global_lock = nil
|
38
|
+
instance_eval(&blk) if blk
|
39
|
+
end
|
40
|
+
|
41
|
+
def register_trigger(trigger)
|
42
|
+
Wakame.log.debug("Registering trigger #{trigger.class}")
|
43
|
+
trigger.bind_engine(self)
|
44
|
+
trigger.register_hooks
|
45
|
+
@triggers << trigger
|
46
|
+
end
|
47
|
+
|
48
|
+
def create_job_context(trigger, root_action)
|
49
|
+
root_action.job_id = job_id = Wakame.gen_id
|
50
|
+
|
51
|
+
@active_jobs[job_id] = {
|
52
|
+
:job_id=>job_id,
|
53
|
+
:src_trigger=>trigger,
|
54
|
+
:create_at=>Time.now,
|
55
|
+
:start_at=>nil,
|
56
|
+
:complete_at=>nil,
|
57
|
+
:root_action=>root_action,
|
58
|
+
:notes=>{}
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
def cancel_action(job_id)
|
63
|
+
job_context = @active_jobs[job_id]
|
64
|
+
if job_context.nil?
|
65
|
+
Wakame.log.warn("JOB ID #{job_id} was not running.")
|
66
|
+
return
|
67
|
+
end
|
68
|
+
|
69
|
+
return if job_context[:complete_at]
|
70
|
+
|
71
|
+
root_act = job_context[:root_action]
|
72
|
+
|
73
|
+
walk_subactions = proc { |a|
|
74
|
+
if a.status == :running && (a.target_thread && a.target_thread.alive?) && a.target_thread != Thread.current
|
75
|
+
Wakame.log.debug "Raising CancelBroadcast exception: #{a.class} #{a.target_thread}(#{a.target_thread.status}), current=#{Thread.current}"
|
76
|
+
# Broadcast the special exception to all
|
77
|
+
a.target_thread.raise(CancelBroadcast, "It's broadcasted from #{a.class}")
|
78
|
+
# IMPORTANT: Ensure the worker thread to handle the exception.
|
79
|
+
#Thread.pass
|
80
|
+
end
|
81
|
+
a.subactions.each { |n|
|
82
|
+
walk_subactions.call(n)
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
begin
|
87
|
+
Thread.critical = true
|
88
|
+
walk_subactions.call(root_act)
|
89
|
+
ensure
|
90
|
+
Thread.critical = false
|
91
|
+
# IMPORTANT: Ensure the worker thread to handle the exception.
|
92
|
+
Thread.pass
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def run_action(action)
|
97
|
+
job_context = @active_jobs[action.job_id]
|
98
|
+
raise "The job session is killed.: job_id=#{action.job_id}" if job_context.nil?
|
99
|
+
|
100
|
+
if action.acquire_lock
|
101
|
+
if @global_lock.nil?
|
102
|
+
@global_lock = action.job_id
|
103
|
+
else
|
104
|
+
unless @global_lock == action.job_id
|
105
|
+
raise GlobalLockError, "Global Lock is already acquired by the JobID: #{@global_lock}"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
EM.next_tick {
|
111
|
+
|
112
|
+
begin
|
113
|
+
|
114
|
+
if job_context[:start_at].nil?
|
115
|
+
job_context[:start_at] = Time.new
|
116
|
+
ED.fire_event(Event::JobStart.new(action.job_id))
|
117
|
+
end
|
118
|
+
|
119
|
+
EM.defer proc {
|
120
|
+
res = nil
|
121
|
+
begin
|
122
|
+
action.bind_thread(Thread.current)
|
123
|
+
action.status = :running
|
124
|
+
Wakame.log.debug("Start action : #{action.class.to_s} triggered by [#{action.trigger.class}]")
|
125
|
+
ED.fire_event(Event::ActionStart.new(action))
|
126
|
+
begin
|
127
|
+
action.run
|
128
|
+
action.completion_status = :succeeded
|
129
|
+
Wakame.log.debug("Complete action : #{action.class.to_s}")
|
130
|
+
ED.fire_event(Event::ActionComplete.new(action))
|
131
|
+
end
|
132
|
+
rescue CancelBroadcast => e
|
133
|
+
Wakame.log.info("Received cancel signal: #{e}")
|
134
|
+
action.completion_status = :canceled
|
135
|
+
begin
|
136
|
+
action.on_canceled
|
137
|
+
rescue => e
|
138
|
+
Wakame.log.error(e)
|
139
|
+
end
|
140
|
+
ED.fire_event(Event::ActionFailed.new(action, e))
|
141
|
+
res = e
|
142
|
+
rescue => e
|
143
|
+
Wakame.log.debug("Failed action : #{action.class.to_s} due to #{e}")
|
144
|
+
Wakame.log.error(e)
|
145
|
+
action.completion_status = :failed
|
146
|
+
begin
|
147
|
+
action.on_failed
|
148
|
+
rescue => e
|
149
|
+
Wakame.log.error(e)
|
150
|
+
end
|
151
|
+
ED.fire_event(Event::ActionFailed.new(action, e))
|
152
|
+
# Escalate the cancelation event to parents.
|
153
|
+
unless action.parent_action.nil?
|
154
|
+
action.parent_action.notify(e)
|
155
|
+
end
|
156
|
+
# Force to cancel the current job when the root action ignored the elevated exception.
|
157
|
+
if action === job_context[:root_action]
|
158
|
+
Wakame.log.warn("The escalated exception (#{e.class}) has reached to the root action (#{action.class}). Forcing to cancel the current job #{job_context[:job_id]}")
|
159
|
+
cancel_action(job_context[:job_id]) #rescue Wakame.log.error($!)
|
160
|
+
end
|
161
|
+
res = e
|
162
|
+
ensure
|
163
|
+
action.status = :complete
|
164
|
+
action.bind_thread(nil)
|
165
|
+
end
|
166
|
+
|
167
|
+
res
|
168
|
+
}, proc { |res|
|
169
|
+
unless @active_jobs.has_key?(job_context[:job_id])
|
170
|
+
next
|
171
|
+
end
|
172
|
+
|
173
|
+
jobary = []
|
174
|
+
job_context[:root_action].walk_subactions {|a| jobary << a }
|
175
|
+
Wakame.log.debug(jobary.collect{|a| {a.class.to_s=>a.status}}.inspect)
|
176
|
+
|
177
|
+
if res.is_a?(Exception)
|
178
|
+
job_context[:exception]=res
|
179
|
+
end
|
180
|
+
|
181
|
+
if jobary.all? { |act| act.status == :complete }
|
182
|
+
|
183
|
+
if jobary.all? { |act| act.completion_status == :succeeded }
|
184
|
+
ED.fire_event(Event::JobComplete.new(action.job_id))
|
185
|
+
else
|
186
|
+
ED.fire_event(Event::JobFailed.new(action.job_id, res))
|
187
|
+
end
|
188
|
+
|
189
|
+
job_context[:complete_at]=Time.now
|
190
|
+
@job_history << job_context
|
191
|
+
@active_jobs.delete(job_context[:job_id])
|
192
|
+
@global_lock = nil
|
193
|
+
end
|
194
|
+
}
|
195
|
+
rescue => e
|
196
|
+
Wakame.log.error(e)
|
197
|
+
end
|
198
|
+
}
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
|
2
|
+
require 'uri'
|
3
|
+
require 'ext/uri'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
require 'drb/drb'
|
7
|
+
|
8
|
+
require 'erb'
|
9
|
+
|
10
|
+
require 'wakame'
|
11
|
+
#require 'wakame/util'
|
12
|
+
|
13
|
+
$root_constants = Module.constants
|
14
|
+
|
15
|
+
module Wakame
|
16
|
+
module Runner
|
17
|
+
class AdministratorCommand
|
18
|
+
|
19
|
+
attr_reader :options
|
20
|
+
|
21
|
+
def initialize(args)
|
22
|
+
@args = args.dup
|
23
|
+
@options = {
|
24
|
+
:command_server_uri => Wakame.config.drb_command_server_uri
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def parse(args=@args)
|
29
|
+
args = args.dup
|
30
|
+
|
31
|
+
comm_parser = OptionParser.new { |opts|
|
32
|
+
opts.banner = "Usage: wakameadm [options] command [options]"
|
33
|
+
|
34
|
+
opts.separator ""
|
35
|
+
opts.separator "options:"
|
36
|
+
opts.on( "-s", "--server DrbURI", "command server" ) {|str| @options[:command_server_uri] = str }
|
37
|
+
}
|
38
|
+
|
39
|
+
|
40
|
+
comm_parser.order!(args)
|
41
|
+
@options.freeze
|
42
|
+
return parse_subcommand(args)
|
43
|
+
end
|
44
|
+
|
45
|
+
def run
|
46
|
+
subcommand = parse
|
47
|
+
|
48
|
+
begin
|
49
|
+
cmd_queue = DRbObject.new_with_uri(@options[:command_server_uri])
|
50
|
+
#res = cmd_queue.send_cmd(Marshal.dump(subcommand))
|
51
|
+
subcommand = cmd_queue.send_cmd(subcommand)
|
52
|
+
if subcommand.is_a? Exception
|
53
|
+
STDERR.puts subcommand
|
54
|
+
exit 1
|
55
|
+
end
|
56
|
+
#res = cmd_queue.send(subcommand.class.command_name)
|
57
|
+
rescue => e
|
58
|
+
STDERR.puts e
|
59
|
+
exit 1
|
60
|
+
end
|
61
|
+
|
62
|
+
subcommand.print_result
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def parse_subcommand(args)
|
68
|
+
@subcmd = args.shift
|
69
|
+
if @subcmd.nil?
|
70
|
+
fail "Please pass a sub command."
|
71
|
+
end
|
72
|
+
|
73
|
+
subcommands = {}
|
74
|
+
(Wakame::Command.constants - $root_constants).each { |c|
|
75
|
+
const = Util.build_const("Wakame::Command::#{c}")
|
76
|
+
if const.is_a?(Class)
|
77
|
+
cmdobj = nil
|
78
|
+
begin
|
79
|
+
cmdobj = const.new
|
80
|
+
raise '' unless cmdobj.kind_of?(Wakame::Command)
|
81
|
+
rescue => e
|
82
|
+
next
|
83
|
+
end
|
84
|
+
|
85
|
+
subcommands[cmdobj.class.command_name] = cmdobj
|
86
|
+
end
|
87
|
+
}
|
88
|
+
|
89
|
+
subcommand = subcommands[@subcmd]
|
90
|
+
fail "No such sub command: #{@subcmd}" if subcommand.nil?
|
91
|
+
|
92
|
+
subcommand.parse(args)
|
93
|
+
subcommand
|
94
|
+
# opt_parser = subcommand[:opt_parser]
|
95
|
+
# if opt_parser
|
96
|
+
# sub_parser = OptionParser.new &opt_parser
|
97
|
+
# sub_parser.order!(@tmp_args)
|
98
|
+
# end
|
99
|
+
|
100
|
+
# left_parser = [:left_parser]
|
101
|
+
# if left_parser
|
102
|
+
# begin
|
103
|
+
# instance_eval(&left_parser)
|
104
|
+
# rescue CommandArgumentError => e
|
105
|
+
# fail e
|
106
|
+
# end
|
107
|
+
# end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
|
4
|
+
require 'amqp'
|
5
|
+
|
6
|
+
require 'uri'
|
7
|
+
require 'ext/uri'
|
8
|
+
require 'optparse'
|
9
|
+
|
10
|
+
module Wakame
|
11
|
+
module Runner
|
12
|
+
class Agent
|
13
|
+
include Wakame::Daemonize
|
14
|
+
|
15
|
+
def initialize(argv)
|
16
|
+
@argv = argv.dup
|
17
|
+
|
18
|
+
@options = {
|
19
|
+
:amqp_server => URI.parse('amqp://guest@localhost/'),
|
20
|
+
:log_file => '/var/log/wakame-agent.log',
|
21
|
+
:pid_file => '/var/run/wakame/wakame-agent.pid',
|
22
|
+
:daemonize => true
|
23
|
+
}
|
24
|
+
|
25
|
+
parser.parse! @argv
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def parser
|
30
|
+
@parser ||= OptionParser.new do |opts|
|
31
|
+
opts.banner = "Usage: agent [options]"
|
32
|
+
|
33
|
+
opts.separator ""
|
34
|
+
opts.separator "Agent options:"
|
35
|
+
opts.on( "-p", "--pid PIDFILE", "pid file path" ) {|str| @options[:pid_file] = str }
|
36
|
+
opts.on( "-s", "--server AMQP_URI", "amqp server" ) {|str|
|
37
|
+
begin
|
38
|
+
@options[:amqp_server] = URI.parse(str)
|
39
|
+
rescue URI::InvalidURIError => e
|
40
|
+
fail "#{e}"
|
41
|
+
end
|
42
|
+
}
|
43
|
+
opts.on("-X", "", "daemonize flag" ) { @options[:daemonize] = false }
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
def run
|
52
|
+
%w(QUIT INT TERM).each { |i|
|
53
|
+
Signal.trap(i) { Wakame::Agent.stop{ remove_pidfile } }
|
54
|
+
}
|
55
|
+
|
56
|
+
unless @options[:amqp_server].nil?
|
57
|
+
uri = @options[:amqp_server]
|
58
|
+
default = ::AMQP.settings
|
59
|
+
opts = {:host => uri.host,
|
60
|
+
:port => uri.port || default[:port],
|
61
|
+
:vhost => uri.vhost || default[:vhost],
|
62
|
+
:user=>uri.user || default[:user],
|
63
|
+
:pass=>uri.password ||default[:pass]
|
64
|
+
}
|
65
|
+
else
|
66
|
+
opts = nil
|
67
|
+
end
|
68
|
+
|
69
|
+
if @options[:daemonize]
|
70
|
+
daemonize(@options[:log_file])
|
71
|
+
end
|
72
|
+
|
73
|
+
EM.epoll if Wakame.config.eventmachine_use_epoll
|
74
|
+
EM.run {
|
75
|
+
Wakame::Agent.start(opts)
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|