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,77 @@
1
+ #!/bin/bash
2
+
3
+ [ $UID -eq 0 ] || { echo "Run with root user."; exit 1; }
4
+
5
+ apt-get update;
6
+ apt-get -y upgrade;
7
+
8
+ apt-get -y install apache2-mpm-prefork libapache2-mod-rpaf
9
+ apt-get -y install mysql-server mysql-client
10
+ apt-get -y install erlang-nox
11
+ apt-get -y install unzip zip rsync libopenssl-ruby libhmac-ruby rubygems irb ri rdoc sysstat
12
+
13
+ apt-get clean
14
+
15
+ (cd /tmp;
16
+ wget http://www.rabbitmq.com/releases/rabbitmq-server/v1.5.4/rabbitmq-server_1.5.4-1_all.deb;
17
+ dpkg -i rabbitmq-server_1.5.4-1_all.deb;
18
+ )
19
+
20
+
21
+ if ! getent group wakame >/dev/null; then
22
+ addgroup --system wakame
23
+ fi
24
+
25
+ if ! getent passwd wakame >/dev/null; then
26
+ adduser --system --ingroup wakame --disabled-password wakame
27
+ fi
28
+
29
+ mkdir /home/wakame/config
30
+ chown wakame:wakame /home/wakame/config
31
+ mkdir /home/wakame/mysql
32
+ mkdir /home/wakame/mysql/data
33
+ mkdir /home/wakame/mysql/data-slave
34
+ chown mysql:mysql /home/wakame/mysql/data /home/wakame/mysql/data-slave
35
+
36
+ if ! grep GEM_HOME /etc/environemnt >/dev/null; then
37
+ cat <<EOF > /etc/environment
38
+ GEM_HOME=/usr/local/gems
39
+ EOF
40
+ fi
41
+
42
+ cat <<EOF > /etc/default/wakame
43
+ WAKAME_HOME=/home/wakame/corelib
44
+ GEM_HOME=/usr/local/gems
45
+ EOF
46
+
47
+ update-rc.d -f apache2 remove
48
+ update-rc.d -f mysql remove
49
+ update-rc.d -f mysql-ndb remove
50
+ update-rc.d -f mysql-ndb-mgm remove
51
+ # Disable apparmor
52
+ update-rc.d -f apparmor remove
53
+
54
+ cat <<EOF > /usr/local/bin/passenger_ruby.sh
55
+ #!/bin/sh
56
+ export GEM_PATH="/usr/local/gems"
57
+ exec /usr/bin/ruby $@
58
+ EOF
59
+ chmod 755 /usr/local/bin/passenger_ruby.sh
60
+
61
+ # Create root ssh key
62
+ ssh-keygen -t rsa -N '' -f /home/wakame/config/root.id_rsa
63
+ chown wakame:wakame /home/wakame/config/root.id_rsa /home/wakame/config/root.id_rsa.pub
64
+ cat /home/wakame/config/root.id_rsa.pub >> /root/.ssh/authorized_keys
65
+
66
+ #gem install rake rails eventmachine amqp log4r daemons passenger hoe amazon-ec2 --no-ri --no-rdoc
67
+ #(cd $GEM_HOME/gems/passenger-*; rake)
68
+
69
+ #update-rc.d wakame-master defaults 41
70
+ #update-rc.d wakame-agent defaults 40
71
+
72
+ #
73
+ # /root/.ssh/authorized_keys /root/.bash_history
74
+ # /home/ubuntu/.ssh/authorized_keys /home/ubuntu/.bash_history
75
+ # Clear logs
76
+ # logrotate -f /etc/logrotate.conf
77
+ # rm -f /var/log/apache2/* /var/log/rabbitmq/* /var/log/wakame-* /var/log/*.gz /var/log/*.0 /var/log/*.1
@@ -0,0 +1,86 @@
1
+
2
+ require 'thread'
3
+
4
+ module EventMachine
5
+ # def self::defer op, callback = nil
6
+ # @need_threadqueue ||= 0
7
+ # if @need_threadqueue == 0
8
+ # @need_threadqueue = 1
9
+ # require 'thread'
10
+ # @threadqueue = Queue.new
11
+ # @resultqueue = Queue.new
12
+ # @thread_g = ThreadGroup.new
13
+ # 20.times {|ix|
14
+ # t = Thread.new {
15
+ # my_ix = ix
16
+ # loop {
17
+ # op,cback = @threadqueue.pop
18
+ # begin
19
+ # result = op.call
20
+ # @resultqueue << [result, cback]
21
+ # rescue => e
22
+ # puts "#{e} in EM defer thread pool : #{Thread.current}"
23
+ # raise e
24
+ # ensure
25
+ # EventMachine.signal_loopbreak
26
+ # end
27
+ # }
28
+ # }
29
+ # @thread_g.add(t)
30
+ # }
31
+ # end
32
+ #
33
+ # @threadqueue << [op,callback]
34
+ # end
35
+
36
+ # Redefine EM's threadpool
37
+ def self.spawn_threadpool
38
+ until @threadpool.size == 20
39
+ thread = Thread.new {
40
+ loop {
41
+ op, cback = *@threadqueue.pop
42
+ begin
43
+ result = op.call
44
+ @resultqueue << [result, cback]
45
+ rescue => e
46
+ puts "#{e} in EM defer thread pool : #{Thread.current}"
47
+ ensure
48
+ EventMachine.signal_loopbreak
49
+ end
50
+ }
51
+ }
52
+ @threadpool << thread
53
+ end
54
+ end
55
+
56
+ def self.barrier(&blk)
57
+ # Presumably, Thread.main will return the EM main loop thread.
58
+ if EM.reactor_thread?
59
+ return blk.call
60
+ end
61
+
62
+ raise "Eventmachine is not ready to accept the next_tick() call." unless self.reactor_running?
63
+
64
+ @q ||= ::Queue.new
65
+ time_start = ::Time.now
66
+
67
+ self.next_tick {
68
+ #self.add_timer(0) {
69
+ begin
70
+ res = blk.call
71
+ @q << [true, res]
72
+ rescue => e
73
+ @q << [false, e]
74
+ end
75
+ }
76
+
77
+ res = @q.shift
78
+ time_elapsed = ::Time.now - time_start
79
+ Wakame.log.debug("EM.barrier: elapsed time for #{blk}: #{time_elapsed} sec (#{$eventmachine_library})") if time_elapsed > 0.05
80
+ if res[0] == false && res[1].is_a?(Exception)
81
+ raise res[1]
82
+ end
83
+ res[1]
84
+ end
85
+
86
+ end
@@ -0,0 +1,172 @@
1
+ #
2
+ # shellwords.rb: Manipulates strings a la UNIX Bourne shell
3
+ #
4
+
5
+ #
6
+ # This module manipulates strings according to the word parsing rules
7
+ # of the UNIX Bourne shell.
8
+ #
9
+ # The shellwords() function was originally a port of shellwords.pl,
10
+ # but modified to conform to POSIX / SUSv3 (IEEE Std 1003.1-2001).
11
+ #
12
+ # Authors:
13
+ # - Wakou Aoyama
14
+ # - Akinori MUSHA <knu@iDaemons.org>
15
+ #
16
+ # Contact:
17
+ # - Akinori MUSHA <knu@iDaemons.org> (current maintainer)
18
+ #
19
+ module Shellwords
20
+ #
21
+ # Splits a string into an array of tokens in the same way the UNIX
22
+ # Bourne shell does.
23
+ #
24
+ # argv = Shellwords.split('here are "two words"')
25
+ # argv #=> ["here", "are", "two words"]
26
+ #
27
+ # +String#shellsplit+ is a shorthand for this function.
28
+ #
29
+ # argv = 'here are "two words"'.shellsplit
30
+ # argv #=> ["here", "are", "two words"]
31
+ #
32
+ def shellsplit(line)
33
+ line = String.new(line) rescue
34
+ raise(ArgumentError, "Argument must be a string")
35
+ line.lstrip!
36
+ words = []
37
+ until line.empty?
38
+ field = ''
39
+ loop do
40
+ if line.sub!(/\A"(([^"\\]|\\.)*)"/, '') then
41
+ snippet = $1.gsub(/\\(.)/, '\1')
42
+ elsif line =~ /\A"/ then
43
+ raise ArgumentError, "Unmatched double quote: #{line}"
44
+ elsif line.sub!(/\A'([^']*)'/, '') then
45
+ snippet = $1
46
+ elsif line =~ /\A'/ then
47
+ raise ArgumentError, "Unmatched single quote: #{line}"
48
+ elsif line.sub!(/\A\\(.)?/, '') then
49
+ snippet = $1 || '\\'
50
+ elsif line.sub!(/\A([^\s\\'"]+)/, '') then
51
+ snippet = $1
52
+ else
53
+ line.lstrip!
54
+ break
55
+ end
56
+ field.concat(snippet)
57
+ end
58
+ words.push(field)
59
+ end
60
+ words
61
+ end
62
+
63
+ alias shellwords shellsplit
64
+
65
+ module_function :shellsplit, :shellwords
66
+
67
+ class << self
68
+ alias split shellsplit
69
+ end
70
+
71
+ #
72
+ # Escapes a string so that it can be safely used in a Bourne shell
73
+ # command line.
74
+ #
75
+ # Note that a resulted string should be used unquoted and is not
76
+ # intended for use in double quotes nor in single quotes.
77
+ #
78
+ # open("| grep #{Shellwords.escape(pattern)} file") { |pipe|
79
+ # # ...
80
+ # }
81
+ #
82
+ # +String#shellescape+ is a shorthand for this function.
83
+ #
84
+ # open("| grep #{pattern.shellescape} file") { |pipe|
85
+ # # ...
86
+ # }
87
+ #
88
+ def shellescape(str)
89
+ # An empty argument will be skipped, so return empty quotes.
90
+ return "''" if str.empty?
91
+
92
+ str = str.dup
93
+
94
+ # Process as a single byte sequence because not all shell
95
+ # implementations are multibyte aware.
96
+ str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/n, "\\\\\\1")
97
+
98
+ # A LF cannot be escaped with a backslash because a backslash + LF
99
+ # combo is regarded as line continuation and simply ignored.
100
+ str.gsub!(/\n/, "'\n'")
101
+
102
+ return str
103
+ end
104
+
105
+ module_function :shellescape
106
+
107
+ class << self
108
+ alias escape shellescape
109
+ end
110
+
111
+ #
112
+ # Builds a command line string from an argument list +array+ joining
113
+ # all elements escaped for Bourne shell and separated by a space.
114
+ #
115
+ # open('|' + Shellwords.join(['grep', pattern, *files])) { |pipe|
116
+ # # ...
117
+ # }
118
+ #
119
+ # +Array#shelljoin+ is a shorthand for this function.
120
+ #
121
+ # open('|' + ['grep', pattern, *files].shelljoin) { |pipe|
122
+ # # ...
123
+ # }
124
+ #
125
+ def shelljoin(array)
126
+ array.map { |arg| shellescape(arg) }.join(' ')
127
+ end
128
+
129
+ module_function :shelljoin
130
+
131
+ class << self
132
+ alias join shelljoin
133
+ end
134
+ end
135
+
136
+ class String
137
+ #
138
+ # call-seq:
139
+ # str.shellsplit => array
140
+ #
141
+ # Splits +str+ into an array of tokens in the same way the UNIX
142
+ # Bourne shell does. See +Shellwords::shellsplit+ for details.
143
+ #
144
+ def shellsplit
145
+ Shellwords.split(self)
146
+ end
147
+
148
+ #
149
+ # call-seq:
150
+ # str.shellescape => string
151
+ #
152
+ # Escapes +str+ so that it can be safely used in a Bourne shell
153
+ # command line. See +Shellwords::shellescape+ for details.
154
+ #
155
+ def shellescape
156
+ Shellwords.escape(self)
157
+ end
158
+ end
159
+
160
+ class Array
161
+ #
162
+ # call-seq:
163
+ # array.shelljoin => string
164
+ #
165
+ # Builds a command line string from an argument list +array+ joining
166
+ # all elements escaped for Bourne shell and separated by a space.
167
+ # See +Shellwords::shelljoin+ for details.
168
+ #
169
+ def shelljoin
170
+ Shellwords.join(self)
171
+ end
172
+ end
data/lib/ext/uri.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'uri/generic'
2
+
3
+ module URI
4
+ class AMQP < Generic
5
+ COMPONENT = [
6
+ :scheme,
7
+ :userinfo, :host, :port,
8
+ :path
9
+ ].freeze
10
+
11
+ alias :vhost :path
12
+ end
13
+
14
+ @@schemes['AMQP'] = AMQP
15
+ end
@@ -0,0 +1,156 @@
1
+ module Wakame
2
+ class Action
3
+ include AttributeHelper
4
+ include ThreadImmutable
5
+
6
+ def_attribute :job_id
7
+ def_attribute :status, :ready
8
+ def_attribute :completion_status
9
+ def_attribute :parent_action
10
+ def_attribute :acquire_lock, false
11
+
12
+ attr_reader :trigger
13
+
14
+ def master
15
+ trigger.master
16
+ end
17
+
18
+ def agent_monitor
19
+ trigger.agent_monitor
20
+ end
21
+
22
+ def service_cluster
23
+ trigger.service_cluster
24
+ end
25
+ def status=(status)
26
+ if @status != status
27
+ @status = status
28
+ # Notify to observers after updating the attribute
29
+ notify
30
+ end
31
+ @status
32
+ end
33
+ thread_immutable_methods :status=
34
+
35
+ def subactions
36
+ @subactions ||= []
37
+ end
38
+
39
+ def bind_triggered_rule(trigger)
40
+ @trigger = trigger
41
+ end
42
+
43
+ def trigger_action(subaction, opts={})
44
+ if opts.is_a? Hash
45
+ succ_proc = opts[:success] || opts[:succ]
46
+ fail_proc = opts[:fail]
47
+ end
48
+ subactions << subaction
49
+ subaction.parent_action = self
50
+ #subaction.observers << self
51
+
52
+ async_trigger_action(subaction, succ_proc, fail_proc)
53
+ end
54
+
55
+ def flush_subactions(sec=nil)
56
+ job_context = trigger.rule_engine.active_jobs[self.job_id]
57
+ return if job_context.nil?
58
+
59
+ timeout(sec.nil? ? nil : sec) {
60
+ until all_subactions_complete?
61
+ #Wakame.log.debug "#{self.class} all_subactions_complete?=#{all_subactions_complete?}"
62
+ src = notify_queue.deq
63
+ # Exit the current action when a subaction notified exception.
64
+ if src.is_a?(Exception)
65
+ raise src
66
+ end
67
+ #Wakame.log.debug "#{self.class} notified by #{src.class}, all_subactions_complete?=#{all_subactions_complete?}"
68
+ end
69
+ }
70
+ end
71
+
72
+ def all_subactions_complete?
73
+ subactions.each { |a|
74
+ #Wakame.log.debug("#{a.class}.status=#{a.status}")
75
+ return false unless a.status == :complete && a.all_subactions_complete?
76
+ }
77
+ true
78
+ end
79
+
80
+ def notify_queue
81
+ @notify_queue ||= ::Queue.new
82
+ end
83
+
84
+ def notify(src=nil)
85
+ #Wakame.log.debug("#{self.class}.notify() has been called")
86
+ src = self if src.nil?
87
+ if status == :complete && parent_action
88
+ # Escalate the notification to parent if the action is finished.
89
+ parent_action.notify(src)
90
+ else
91
+ notify_queue.clear if notify_queue.size > 0
92
+ notify_queue.enq(src) #if notify_queue.num_waiting > 0
93
+ end
94
+ end
95
+
96
+
97
+ def walk_subactions(&blk)
98
+ blk.call(self)
99
+ self.subactions.each{ |a|
100
+ a.walk_subactions(&blk)
101
+ }
102
+ end
103
+
104
+ def actor_request(agent_id, path, *args, &blk)
105
+ request = master.actor_request(agent_id, path, *args)
106
+ if blk
107
+ request.request
108
+ blk.call(request)
109
+ end
110
+ request
111
+ end
112
+
113
+ def sync_actor_request(agent_id, path, *args)
114
+ request = actor_request(agent_id, path, *args).request
115
+ request.wait
116
+ end
117
+
118
+ def notes
119
+ trigger.rule_engine.active_jobs[self.job_id][:notes]
120
+ end
121
+
122
+ def run
123
+ raise NotImplementedError
124
+ end
125
+
126
+ def on_failed
127
+ end
128
+
129
+ def on_canceled
130
+ end
131
+
132
+ private
133
+ def sync_trigger_action(action, succ_proc, fail_proc)
134
+ action.job_id = self.job_id
135
+ action.bind_triggered_rule(self.trigger)
136
+
137
+ Wakame.log.debug("Start nested action in SYNC: #{action.class.to_s}")
138
+ begin
139
+ action.run
140
+ succ_proc.call if succ_proc
141
+ rescue => e
142
+ fail_proc.call if fail_proc
143
+ raise
144
+ end
145
+ Wakame.log.debug("Complete nested action : #{action.class.to_s}")
146
+ end
147
+
148
+ def async_trigger_action(action, succ_proc, fail_proc)
149
+ action.job_id = self.job_id
150
+ action.bind_triggered_rule(self.trigger)
151
+
152
+ trigger.rule_engine.run_action(action)
153
+ end
154
+
155
+ end
156
+ end
@@ -0,0 +1,39 @@
1
+ module Wakame
2
+ module Actions
3
+ class DestroyInstances < Action
4
+ def initialize(svc_prop)
5
+ @svc_prop = svc_prop
6
+ end
7
+
8
+ def run
9
+ svc_to_stop=[]
10
+
11
+ EM.barrier {
12
+ online_svc = []
13
+ service_cluster.each_instance(@svc_prop.class) { |svc_inst|
14
+ if svc_inst.status == Service::STATUS_ONLINE
15
+ online_svc << svc_inst
16
+ end
17
+ }
18
+
19
+ svc_count = service_cluster.instance_count(@svc_prop)
20
+ if svc_count < online_svc.size
21
+ online_svc.delete_if { |svc|
22
+ svc.agent.agent_id == master.attr[:instance_id]
23
+ }
24
+
25
+ ((online_svc.size - svc_count) + 1).times {
26
+ svc_to_stop << online_svc.shift
27
+ }
28
+ Wakame.log.debug("#{self.class}: online_svc.size=#{online_svc.size}, svc_to_stop.size=#{svc_to_stop.size}")
29
+ end
30
+ }
31
+
32
+ svc_to_stop.each { |svc_inst|
33
+ trigger_action(StopService.new(svc_inst))
34
+ }
35
+ flush_subactions
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,31 @@
1
+ module Wakame
2
+ module Actions
3
+ class LaunchCluster < Action
4
+ def initialize
5
+ @acquire_lock = true
6
+ end
7
+
8
+ def run
9
+ if service_cluster.status == Service::ServiceCluster::STATUS_ONLINE
10
+ Wakame.log.info("The service cluster is up & running already")
11
+ raise CancelActionError
12
+ end
13
+
14
+ EM.barrier {
15
+ service_cluster.launch
16
+ }
17
+
18
+ Wakame.log.debug("#{self.class}: Resource Launch Order: " + service_cluster.dg.levels.collect {|lv| '['+ lv.collect{|prop| "#{prop.class}" }.join(', ') + ']' }.join(', '))
19
+
20
+ service_cluster.dg.levels.each { |lv|
21
+ lv.each { |svc_prop|
22
+ trigger_action(PropagateInstances.new(svc_prop))
23
+ }
24
+ flush_subactions
25
+ Wakame.log.debug("#{self.class}: DG level next")
26
+ }
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,65 @@
1
+
2
+ require 'wakame/actions/util'
3
+
4
+ module Wakame
5
+ module Actions
6
+ class MigrateService < Action
7
+ include Actions::Util
8
+
9
+ def initialize(service_instance, dest_agent=nil)
10
+ @service_instance = service_instance
11
+ @destination_agent = dest_agent
12
+ end
13
+
14
+ def run
15
+ raise CancelActionError if @service_instance.status == Service::STATUS_MIGRATING
16
+
17
+ EM.barrier {
18
+ @service_instance.update_status(Service::STATUS_MIGRATING)
19
+ }
20
+ prop = @service_instance.property
21
+ if prop.duplicable
22
+ clone_service(prop)
23
+ flush_subactions
24
+ trigger_action(StopService.new(@service_instance))
25
+ else
26
+
27
+ trigger_action(StopService.new(@service_instance))
28
+ flush_subactions
29
+ clone_service(prop)
30
+ end
31
+ flush_subactions
32
+ end
33
+
34
+ private
35
+ def clone_service(resource)
36
+ new_svc = nil
37
+ EM.barrier {
38
+ new_svc = service_cluster.propagate(resource, true)
39
+ }
40
+
41
+ agent = @destination_agent
42
+ if agent.nil?
43
+ EM.barrier {
44
+ agent = arrange_agent(resource)
45
+ }
46
+ if agent.nil?
47
+ inst_id = start_instance(master.attr[:ami_id], resource.vm_spec.current.attrs)
48
+ agent = agent_monitor.registered_agents[inst_id]
49
+ end
50
+ end
51
+
52
+ if !(agent && test_agent_candidate(resource, agent))
53
+ raise "Found confiction(s) when the agent is assigned to sevice: #{resource} #{agent} "
54
+ end
55
+
56
+ EM.barrier {
57
+ new_svc.bind_agent(agent)
58
+ }
59
+
60
+ trigger_action(StartService.new(new_svc))
61
+ new_svc
62
+ end
63
+ end
64
+ end
65
+ end