wakame 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. data/History.txt +20 -0
  2. data/README.rdoc +63 -0
  3. data/Rakefile +86 -0
  4. data/VERSION +1 -0
  5. data/app_generators/wakame/templates/README +0 -0
  6. data/app_generators/wakame/templates/Rakefile +18 -0
  7. data/app_generators/wakame/templates/bin/wakame-agent +9 -0
  8. data/app_generators/wakame/templates/bin/wakame-master +9 -0
  9. data/app_generators/wakame/templates/bin/wakameadm +9 -0
  10. data/app_generators/wakame/templates/cluster/resources/apache_app/apache_app.rb +54 -0
  11. data/app_generators/wakame/templates/cluster/resources/apache_app/conf/apache2.conf +46 -0
  12. data/app_generators/wakame/templates/cluster/resources/apache_app/conf/envvars-app +7 -0
  13. data/app_generators/wakame/templates/cluster/resources/apache_app/conf/sites-app.conf +23 -0
  14. data/app_generators/wakame/templates/cluster/resources/apache_app/conf/system-app.conf +67 -0
  15. data/app_generators/wakame/templates/cluster/resources/apache_app/init.d/apache2-app +192 -0
  16. data/app_generators/wakame/templates/cluster/resources/apache_lb/apache_lb.rb +56 -0
  17. data/app_generators/wakame/templates/cluster/resources/apache_lb/conf/apache2.conf +46 -0
  18. data/app_generators/wakame/templates/cluster/resources/apache_lb/conf/envvars-lb +6 -0
  19. data/app_generators/wakame/templates/cluster/resources/apache_lb/conf/sites-lb.conf +54 -0
  20. data/app_generators/wakame/templates/cluster/resources/apache_lb/conf/system-lb.conf +75 -0
  21. data/app_generators/wakame/templates/cluster/resources/apache_lb/init.d/apache2-lb +192 -0
  22. data/app_generators/wakame/templates/cluster/resources/apache_www/apache_www.rb +50 -0
  23. data/app_generators/wakame/templates/cluster/resources/apache_www/conf/apache2.conf +47 -0
  24. data/app_generators/wakame/templates/cluster/resources/apache_www/conf/envvars-www +7 -0
  25. data/app_generators/wakame/templates/cluster/resources/apache_www/conf/sites-www.conf +23 -0
  26. data/app_generators/wakame/templates/cluster/resources/apache_www/conf/system-www.conf +63 -0
  27. data/app_generators/wakame/templates/cluster/resources/apache_www/init.d/apache2-www +192 -0
  28. data/app_generators/wakame/templates/cluster/resources/ec2_elastic_ip/ec2_elastic_ip.rb +39 -0
  29. data/app_generators/wakame/templates/cluster/resources/mysql_master/conf/my.cnf +154 -0
  30. data/app_generators/wakame/templates/cluster/resources/mysql_master/init.d/mysql +185 -0
  31. data/app_generators/wakame/templates/cluster/resources/mysql_master/mysql_master.rb +174 -0
  32. data/app_generators/wakame/templates/config/boot.rb +85 -0
  33. data/app_generators/wakame/templates/config/cluster.rb +64 -0
  34. data/app_generators/wakame/templates/config/environments/common.rb +0 -0
  35. data/app_generators/wakame/templates/config/environments/ec2.rb +3 -0
  36. data/app_generators/wakame/templates/config/environments/stand_alone.rb +0 -0
  37. data/app_generators/wakame/templates/config/init.d/wakame-agent +72 -0
  38. data/app_generators/wakame/templates/config/init.d/wakame-master +73 -0
  39. data/app_generators/wakame/wakame_generator.rb +124 -0
  40. data/bin/wakame +18 -0
  41. data/contrib/imagesetup.sh +77 -0
  42. data/lib/ext/eventmachine.rb +86 -0
  43. data/lib/ext/shellwords.rb +172 -0
  44. data/lib/ext/uri.rb +15 -0
  45. data/lib/wakame/action.rb +156 -0
  46. data/lib/wakame/actions/destroy_instances.rb +39 -0
  47. data/lib/wakame/actions/launch_cluster.rb +31 -0
  48. data/lib/wakame/actions/migrate_service.rb +65 -0
  49. data/lib/wakame/actions/propagate_instances.rb +95 -0
  50. data/lib/wakame/actions/reload_service.rb +21 -0
  51. data/lib/wakame/actions/scaleout_when_high_load.rb +44 -0
  52. data/lib/wakame/actions/shutdown_cluster.rb +22 -0
  53. data/lib/wakame/actions/shutdown_vm.rb +19 -0
  54. data/lib/wakame/actions/start_service.rb +64 -0
  55. data/lib/wakame/actions/stop_service.rb +49 -0
  56. data/lib/wakame/actions/util.rb +71 -0
  57. data/lib/wakame/actor/daemon.rb +37 -0
  58. data/lib/wakame/actor/service_monitor.rb +21 -0
  59. data/lib/wakame/actor/system.rb +46 -0
  60. data/lib/wakame/actor.rb +33 -0
  61. data/lib/wakame/agent.rb +226 -0
  62. data/lib/wakame/amqp_client.rb +219 -0
  63. data/lib/wakame/command/action_status.rb +62 -0
  64. data/lib/wakame/command/actor.rb +23 -0
  65. data/lib/wakame/command/clone_service.rb +12 -0
  66. data/lib/wakame/command/launch_cluster.rb +15 -0
  67. data/lib/wakame/command/migrate_service.rb +21 -0
  68. data/lib/wakame/command/propagate_service.rb +24 -0
  69. data/lib/wakame/command/shutdown_cluster.rb +15 -0
  70. data/lib/wakame/command/status.rb +81 -0
  71. data/lib/wakame/command.rb +31 -0
  72. data/lib/wakame/command_queue.rb +44 -0
  73. data/lib/wakame/configuration.rb +93 -0
  74. data/lib/wakame/daemonize.rb +96 -0
  75. data/lib/wakame/event.rb +232 -0
  76. data/lib/wakame/event_dispatcher.rb +154 -0
  77. data/lib/wakame/graph.rb +79 -0
  78. data/lib/wakame/initializer.rb +162 -0
  79. data/lib/wakame/instance_counter.rb +78 -0
  80. data/lib/wakame/logger.rb +12 -0
  81. data/lib/wakame/manager/commands.rb +134 -0
  82. data/lib/wakame/master.rb +369 -0
  83. data/lib/wakame/monitor/agent.rb +50 -0
  84. data/lib/wakame/monitor/service.rb +183 -0
  85. data/lib/wakame/monitor.rb +69 -0
  86. data/lib/wakame/packets.rb +160 -0
  87. data/lib/wakame/queue_declare.rb +14 -0
  88. data/lib/wakame/rule.rb +116 -0
  89. data/lib/wakame/rule_engine.rb +202 -0
  90. data/lib/wakame/runner/administrator_command.rb +112 -0
  91. data/lib/wakame/runner/agent.rb +81 -0
  92. data/lib/wakame/runner/master.rb +93 -0
  93. data/lib/wakame/scheduler.rb +251 -0
  94. data/lib/wakame/service.rb +914 -0
  95. data/lib/wakame/template.rb +189 -0
  96. data/lib/wakame/trigger.rb +66 -0
  97. data/lib/wakame/triggers/instance_count_update.rb +45 -0
  98. data/lib/wakame/triggers/load_history.rb +107 -0
  99. data/lib/wakame/triggers/maintain_ssh_known_hosts.rb +43 -0
  100. data/lib/wakame/triggers/process_command.rb +34 -0
  101. data/lib/wakame/triggers/shutdown_unused_vm.rb +16 -0
  102. data/lib/wakame/util.rb +569 -0
  103. data/lib/wakame/vm_manipulator.rb +186 -0
  104. data/lib/wakame.rb +59 -0
  105. data/tasks/ec2.rake +127 -0
  106. data/tests/cluster.json +3 -0
  107. data/tests/conf/a +1 -0
  108. data/tests/conf/b +1 -0
  109. data/tests/conf/c +1 -0
  110. data/tests/setup_agent.rb +39 -0
  111. data/tests/setup_master.rb +28 -0
  112. data/tests/test_actor.rb +54 -0
  113. data/tests/test_agent.rb +218 -0
  114. data/tests/test_amqp_client.rb +94 -0
  115. data/tests/test_graph.rb +36 -0
  116. data/tests/test_master.rb +167 -0
  117. data/tests/test_monitor.rb +47 -0
  118. data/tests/test_rule_engine.rb +127 -0
  119. data/tests/test_scheduler.rb +123 -0
  120. data/tests/test_service.rb +60 -0
  121. data/tests/test_template.rb +67 -0
  122. data/tests/test_uri_amqp.rb +19 -0
  123. data/tests/test_util.rb +71 -0
  124. data/wakame_generators/resource/resource_generator.rb +54 -0
  125. data/wakame_generators/resource/templates/apache_app/apache_app.rb +60 -0
  126. data/wakame_generators/resource/templates/apache_app/conf/apache2.conf +46 -0
  127. data/wakame_generators/resource/templates/apache_app/conf/envvars-app +7 -0
  128. data/wakame_generators/resource/templates/apache_app/conf/sites-app.conf +23 -0
  129. data/wakame_generators/resource/templates/apache_app/conf/system-app.conf +67 -0
  130. data/wakame_generators/resource/templates/apache_app/init.d/apache2-app +192 -0
  131. data/wakame_generators/resource/templates/apache_lb/apache_lb.rb +67 -0
  132. data/wakame_generators/resource/templates/apache_lb/conf/apache2.conf +46 -0
  133. data/wakame_generators/resource/templates/apache_lb/conf/envvars-lb +6 -0
  134. data/wakame_generators/resource/templates/apache_lb/conf/sites-lb.conf +54 -0
  135. data/wakame_generators/resource/templates/apache_lb/conf/system-lb.conf +75 -0
  136. data/wakame_generators/resource/templates/apache_lb/init.d/apache2-lb +192 -0
  137. data/wakame_generators/resource/templates/apache_www/apache_www.rb +56 -0
  138. data/wakame_generators/resource/templates/apache_www/conf/apache2.conf +47 -0
  139. data/wakame_generators/resource/templates/apache_www/conf/envvars-www +7 -0
  140. data/wakame_generators/resource/templates/apache_www/conf/sites-www.conf +23 -0
  141. data/wakame_generators/resource/templates/apache_www/conf/system-www.conf +63 -0
  142. data/wakame_generators/resource/templates/apache_www/init.d/apache2-www +192 -0
  143. data/wakame_generators/resource/templates/ec2_elastic_ip/ec2_elastic_ip.rb +39 -0
  144. data/wakame_generators/resource/templates/mysql_master/conf/my.cnf +154 -0
  145. data/wakame_generators/resource/templates/mysql_master/init.d/mysql +185 -0
  146. data/wakame_generators/resource/templates/mysql_master/mysql_master.rb +119 -0
  147. 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
@@ -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