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,914 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
require 'wakame'
|
6
|
+
require 'wakame/util'
|
7
|
+
|
8
|
+
module Wakame
|
9
|
+
module Service
|
10
|
+
class ServiceError < StandardError; end
|
11
|
+
class ServiceOk < StandardError; end
|
12
|
+
class ServicePropagationError < ServiceError; end
|
13
|
+
|
14
|
+
|
15
|
+
STATUS_OFFLINE = 0
|
16
|
+
STATUS_ONLINE = 1
|
17
|
+
STATUS_UNKNOWN = 2
|
18
|
+
STATUS_FAIL = 3
|
19
|
+
STATUS_STARTING = 4
|
20
|
+
STATUS_STOPPING = 5
|
21
|
+
STATUS_RELOADING = 6
|
22
|
+
STATUS_MIGRATING = 7
|
23
|
+
|
24
|
+
class Agent
|
25
|
+
include ThreadImmutable
|
26
|
+
include AttributeHelper
|
27
|
+
STATUS_OFFLINE = 0
|
28
|
+
STATUS_ONLINE = 1
|
29
|
+
STATUS_UNKNOWN = 2
|
30
|
+
STATUS_TIMEOUT = 3
|
31
|
+
|
32
|
+
attr_accessor :agent_id, :uptime, :last_ping_at, :attr, :services, :root_path
|
33
|
+
thread_immutable_methods :agent_id=, :uptime=, :last_ping_at=, :attr=, :services=, :root_path=
|
34
|
+
|
35
|
+
def initialize(agent_id=nil)
|
36
|
+
bind_thread
|
37
|
+
@services = {}
|
38
|
+
@agent_id = agent_id
|
39
|
+
@last_ping_at = Time.now
|
40
|
+
@status = STATUS_ONLINE
|
41
|
+
end
|
42
|
+
|
43
|
+
def agent_ip
|
44
|
+
attr[:local_ipv4]
|
45
|
+
end
|
46
|
+
|
47
|
+
def [](key)
|
48
|
+
attr[key]
|
49
|
+
end
|
50
|
+
|
51
|
+
attr_reader :status
|
52
|
+
|
53
|
+
def status=(status)
|
54
|
+
if @status != status
|
55
|
+
@status = status
|
56
|
+
ED.fire_event(Event::AgentStatusChanged.new(self))
|
57
|
+
# Send status specific event
|
58
|
+
case status
|
59
|
+
when STATUS_TIMEOUT
|
60
|
+
ED.fire_event(Event::AgentTimedOut.new(self))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
@status
|
64
|
+
end
|
65
|
+
thread_immutable_methods :status=
|
66
|
+
|
67
|
+
def has_service_type?(key)
|
68
|
+
svc_class = case key
|
69
|
+
when Service::ServiceInstance
|
70
|
+
key.resource.class
|
71
|
+
when Service::Resource
|
72
|
+
key.class
|
73
|
+
when Class
|
74
|
+
key
|
75
|
+
else
|
76
|
+
raise ArgumentError
|
77
|
+
end
|
78
|
+
|
79
|
+
services.any? { |k, v|
|
80
|
+
Wakame.log.debug( "#{agent_id} of service #{v.resource.class}. v.resource.class == svc_class result to #{v.resource.class == svc_class}")
|
81
|
+
|
82
|
+
v.property.class == svc_class
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
def dump_status
|
88
|
+
{:agent_id => @agent_id, :status => @status, :last_ping_at => @last_ping_at, :attr => attr.dup,
|
89
|
+
:services => services.keys.dup
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
class ServiceCluster
|
97
|
+
include ThreadImmutable
|
98
|
+
|
99
|
+
attr_reader :dg, :instance_id, :status_changed_at, :rule_engine, :master
|
100
|
+
attr_reader :status
|
101
|
+
|
102
|
+
STATUS_OFFLINE = 0
|
103
|
+
STATUS_ONLINE = 1
|
104
|
+
STATUS_PARTIAL_ONLINE = 2
|
105
|
+
|
106
|
+
def initialize(master, &blk)
|
107
|
+
bind_thread
|
108
|
+
@master = master
|
109
|
+
@instance_id =Wakame.gen_id
|
110
|
+
@rule_engine ||= RuleEngine.new(self)
|
111
|
+
prepare
|
112
|
+
|
113
|
+
instance_eval(&blk) if blk
|
114
|
+
end
|
115
|
+
|
116
|
+
def define_rule(&blk)
|
117
|
+
@rule_engine ||= RuleEngine.new(self)
|
118
|
+
|
119
|
+
blk.call(@rule_engine)
|
120
|
+
end
|
121
|
+
|
122
|
+
def add_resource(resource, name=nil)
|
123
|
+
#if name.nil? || @name2prop.has_key? name
|
124
|
+
# name = "#{resource.class.to_s}#{name2prop.size + 1}"
|
125
|
+
#end
|
126
|
+
raise ArgumentError unless resource.is_a? Resource
|
127
|
+
raise "Duplicate resource type registration" if @properties.has_key? resource.class.to_s
|
128
|
+
@properties[resource.class.to_s]=resource
|
129
|
+
@dg.add_object(resource.class.to_s)
|
130
|
+
|
131
|
+
#name
|
132
|
+
end
|
133
|
+
thread_immutable_methods :add_resource
|
134
|
+
|
135
|
+
def set_dependency(prop_name1, prop_name2)
|
136
|
+
prop1 = @properties[prop_name1.to_s]
|
137
|
+
prop2 = @properties[prop_name2.to_s]
|
138
|
+
return unless prop1.is_a?(Property) && prop2.is_a?(Property) && prop1 != prop2
|
139
|
+
@dg.set_dependency(prop_name1.to_s, prop_name2.to_s)
|
140
|
+
end
|
141
|
+
thread_immutable_methods :set_dependency
|
142
|
+
|
143
|
+
def included_instance?(service_instance_id)
|
144
|
+
@services.has_key? service_instance_id
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
def shutdown
|
149
|
+
end
|
150
|
+
thread_immutable_methods :shutdown
|
151
|
+
|
152
|
+
# Create service instance objects which will be equivalent with the number min_instance.
|
153
|
+
# The agents are not assigned at this point.
|
154
|
+
def launch
|
155
|
+
@properties.each { |n, p|
|
156
|
+
count = instance_count(p)
|
157
|
+
if p.min_instances > count
|
158
|
+
(p.min_instances - count).times {
|
159
|
+
propagate(p.class)
|
160
|
+
}
|
161
|
+
end
|
162
|
+
}
|
163
|
+
end
|
164
|
+
thread_immutable_methods :launch
|
165
|
+
|
166
|
+
def destroy(service_instance_id)
|
167
|
+
raise("Unknown service instance : #{service_instance_id}") unless included_instance?(service_instance_id)
|
168
|
+
svc_inst = @services[service_instance_id]
|
169
|
+
old_agent = svc_inst.unbind_agent
|
170
|
+
svc_inst.unbind_cluster
|
171
|
+
@services.delete(service_instance_id)
|
172
|
+
if old_agent
|
173
|
+
Wakame.log.debug("#{svc_inst.property.class}(#{svc_inst.instance_id}) has been destroied from Agent #{old_agent.agent_id}")
|
174
|
+
else
|
175
|
+
Wakame.log.debug("#{svc_inst.property.class}(#{svc_inst.instance_id}) has been destroied.")
|
176
|
+
end
|
177
|
+
end
|
178
|
+
thread_immutable_methods :destroy
|
179
|
+
|
180
|
+
def propagate(property_name, force=false)
|
181
|
+
property_name = case property_name
|
182
|
+
when Class, String
|
183
|
+
property_name.to_s
|
184
|
+
when Property
|
185
|
+
property_name.class.to_s
|
186
|
+
else
|
187
|
+
raise ArgumentError
|
188
|
+
end
|
189
|
+
prop = @properties[property_name.to_s] || raise("Unknown property name: #{property_name.to_s}")
|
190
|
+
if force == false
|
191
|
+
instnum = instance_count(property_name)
|
192
|
+
if instnum >= prop.max_instances
|
193
|
+
Wakame.log.info("#{prop.class} has been reached max_instance limit: max=#{prop.max_instance}")
|
194
|
+
raise ServicePropagationError, "#{prop.class} has been reached to max_instance limit"
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
svc_inst = Service::ServiceInstance.new(prop)
|
199
|
+
svc_inst.bind_cluster(self)
|
200
|
+
#svc_inst.bind_agent(agent) if agent
|
201
|
+
|
202
|
+
@services[svc_inst.instance_id]=svc_inst
|
203
|
+
svc_inst
|
204
|
+
end
|
205
|
+
thread_immutable_methods :propagate
|
206
|
+
|
207
|
+
def instance_count(property_name=nil)
|
208
|
+
return @services.size if property_name.nil?
|
209
|
+
|
210
|
+
property_name = case property_name
|
211
|
+
when Class, String
|
212
|
+
property_name.to_s
|
213
|
+
when Property
|
214
|
+
property_name.class.to_s
|
215
|
+
else
|
216
|
+
raise ArgumentError
|
217
|
+
end
|
218
|
+
|
219
|
+
raise "Unknown property name: #{property_name}" unless @properties.has_key?(property_name.to_s)
|
220
|
+
c = 0
|
221
|
+
each_instance(property_name) { |svc|
|
222
|
+
c += 1
|
223
|
+
}
|
224
|
+
return c
|
225
|
+
end
|
226
|
+
|
227
|
+
def property_count
|
228
|
+
@properties.size
|
229
|
+
end
|
230
|
+
|
231
|
+
def each_instance(filter_prop_name=nil, &blk)
|
232
|
+
prop_obj = nil
|
233
|
+
if filter_prop_name.is_a? String
|
234
|
+
filter_prop_name = Util.build_const(filter_prop_name)
|
235
|
+
end
|
236
|
+
|
237
|
+
if filter_prop_name.is_a? Module
|
238
|
+
prop_obj = @properties.find { |k, v|
|
239
|
+
v.kind_of? filter_prop_name
|
240
|
+
}
|
241
|
+
if prop_obj.is_a? Array
|
242
|
+
prop_obj = prop_obj[1]
|
243
|
+
else
|
244
|
+
raise("Unknown property name: #{filter_prop_name.to_s}")
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
ary = []
|
249
|
+
if prop_obj.nil?
|
250
|
+
ary = @services.dup
|
251
|
+
else
|
252
|
+
ary = @services.find_all{|k, v| v.property.class == prop_obj.class }
|
253
|
+
ary = Hash[*ary.flatten]
|
254
|
+
end
|
255
|
+
|
256
|
+
ary.each {|k,v| blk.call v } if block_given?
|
257
|
+
ary
|
258
|
+
end
|
259
|
+
alias :select_instance :each_instance
|
260
|
+
|
261
|
+
def status=(new_status)
|
262
|
+
if @status != new_status
|
263
|
+
@status = new_status
|
264
|
+
@status_changed_at = Time.now
|
265
|
+
ED.fire_event(Event::ClusterStatusChanged.new(instance_id, new_status))
|
266
|
+
end
|
267
|
+
@status
|
268
|
+
end
|
269
|
+
thread_immutable_methods :status=
|
270
|
+
|
271
|
+
def size
|
272
|
+
@dg.size
|
273
|
+
end
|
274
|
+
alias :num_services :size
|
275
|
+
|
276
|
+
def properties
|
277
|
+
@properties
|
278
|
+
end
|
279
|
+
|
280
|
+
def instances
|
281
|
+
@services
|
282
|
+
end
|
283
|
+
|
284
|
+
|
285
|
+
def dump_status
|
286
|
+
r = {:name => self.class.to_s, :status => self.status, :instances=>{}, :properties=>{} }
|
287
|
+
|
288
|
+
instances.each { |k, i|
|
289
|
+
r[:instances][k]=i.dump_status
|
290
|
+
}
|
291
|
+
properties.each { |k, i|
|
292
|
+
r[:properties][k] = i.dump_status
|
293
|
+
r[:properties][k][:instances] = each_instance(i.class).collect{|k, v| k }
|
294
|
+
}
|
295
|
+
|
296
|
+
r
|
297
|
+
end
|
298
|
+
thread_immutable_methods :dump_status
|
299
|
+
|
300
|
+
private
|
301
|
+
def prepare
|
302
|
+
@dg = DependencyGraph.new(self)
|
303
|
+
@services = {}
|
304
|
+
|
305
|
+
@properties = {}
|
306
|
+
@name2prop ={}
|
307
|
+
@status = STATUS_OFFLINE
|
308
|
+
@status_changed_at = Time.now
|
309
|
+
@rule_engine = nil
|
310
|
+
|
311
|
+
@status_check_timer = EM::PeriodicTimer.new(5) {
|
312
|
+
update_cluster_status
|
313
|
+
}
|
314
|
+
|
315
|
+
@check_event_tickets = []
|
316
|
+
[Event::ServiceOnline, Event::ServiceOffline, Event::ServiceFailed].each { |evclass|
|
317
|
+
@check_event_tickets << ED.subscribe(evclass) { |event|
|
318
|
+
update_cluster_status
|
319
|
+
}
|
320
|
+
}
|
321
|
+
|
322
|
+
# ED.subscribe(Event::AgentTimedOut) { |event|
|
323
|
+
# svc_in_timedout_agent = service_cluster.instances.select { |k, i|
|
324
|
+
# if !i.agent.nil? && i.agent.agent_id == event.agent.agent_id
|
325
|
+
# i.status = Service::STATUS_FAIL
|
326
|
+
# end
|
327
|
+
# }
|
328
|
+
|
329
|
+
# }
|
330
|
+
end
|
331
|
+
thread_immutable_methods :prepare
|
332
|
+
|
333
|
+
|
334
|
+
def update_cluster_status
|
335
|
+
onlines = []
|
336
|
+
all_offline = false
|
337
|
+
onlines = self.instances.select { |k, i|
|
338
|
+
i.status == Service::STATUS_ONLINE
|
339
|
+
}
|
340
|
+
all_offline = self.instances.all? { |k, i|
|
341
|
+
i.status == Service::STATUS_OFFLINE
|
342
|
+
}
|
343
|
+
#Wakame.log.debug "online instances: #{onlines.size}, assigned instances: #{self.instances.size}"
|
344
|
+
if self.instances.size == 0 || all_offline
|
345
|
+
self.status = Service::ServiceCluster::STATUS_OFFLINE
|
346
|
+
elsif onlines.size == self.instances.size
|
347
|
+
self.status = Service::ServiceCluster::STATUS_ONLINE
|
348
|
+
elsif onlines.size > 0
|
349
|
+
self.status = Service::ServiceCluster::STATUS_PARTIAL_ONLINE
|
350
|
+
end
|
351
|
+
|
352
|
+
end
|
353
|
+
thread_immutable_methods :update_cluster_status
|
354
|
+
|
355
|
+
|
356
|
+
end
|
357
|
+
|
358
|
+
|
359
|
+
class DependencyGraph
|
360
|
+
|
361
|
+
def initialize(service_cluster)
|
362
|
+
@graph = Graph.new
|
363
|
+
@graph.add_vertex(0)
|
364
|
+
@service_cluster = service_cluster
|
365
|
+
@nodes = {}
|
366
|
+
end
|
367
|
+
|
368
|
+
|
369
|
+
def add_object(obj)
|
370
|
+
@nodes[obj.hash] = obj
|
371
|
+
@graph.add_edge(0, obj.hash)
|
372
|
+
self
|
373
|
+
end
|
374
|
+
|
375
|
+
def set_dependency(parent_obj, child_obj)
|
376
|
+
return if parent_obj == child_obj
|
377
|
+
@graph.add_edge(parent_obj.hash, child_obj.hash)
|
378
|
+
@graph.remove_edge(0, child_obj.hash) if @graph.has_edge?(0, child_obj.hash)
|
379
|
+
self
|
380
|
+
end
|
381
|
+
|
382
|
+
def size
|
383
|
+
@graph.size - 1
|
384
|
+
end
|
385
|
+
|
386
|
+
def parents(obj)
|
387
|
+
obj = case obj
|
388
|
+
when Class
|
389
|
+
obj.to_s.hash
|
390
|
+
when String
|
391
|
+
obj.hash
|
392
|
+
else
|
393
|
+
raise ArgumentError
|
394
|
+
end
|
395
|
+
@graph.parents(obj).collect { |hashid| property_obj(hashid) }
|
396
|
+
end
|
397
|
+
|
398
|
+
def children(obj)
|
399
|
+
obj = case obj
|
400
|
+
when Class
|
401
|
+
obj.to_s.hash
|
402
|
+
when String
|
403
|
+
obj.hash
|
404
|
+
else
|
405
|
+
raise ArgumentError
|
406
|
+
end
|
407
|
+
@graph.children(obj).collect { |hashid| property_obj(hashid) }
|
408
|
+
end
|
409
|
+
|
410
|
+
def levels(root=nil)
|
411
|
+
root = case root
|
412
|
+
when nil
|
413
|
+
0
|
414
|
+
when Class
|
415
|
+
root.to_s.hash
|
416
|
+
when String
|
417
|
+
root.hash
|
418
|
+
else
|
419
|
+
raise ArgumentError
|
420
|
+
end
|
421
|
+
n=[]
|
422
|
+
@graph.level_layout(root).each { |l|
|
423
|
+
next if l.size == 1 && l[0] == 0
|
424
|
+
n << l.collect { |hashid| property_obj(hashid)}
|
425
|
+
#n << l.collect { |hashid| @nodes[hashid].to_s }
|
426
|
+
}
|
427
|
+
n
|
428
|
+
end
|
429
|
+
|
430
|
+
def each_level(root=nil, &blk)
|
431
|
+
root = case root
|
432
|
+
when nil
|
433
|
+
0
|
434
|
+
when Class
|
435
|
+
root.to_s.hash
|
436
|
+
when String
|
437
|
+
root.hash
|
438
|
+
else
|
439
|
+
raise ArgumentError
|
440
|
+
end
|
441
|
+
@graph.level_layout(root).each { |l|
|
442
|
+
l.each { |hashid|
|
443
|
+
next if hashid == 0
|
444
|
+
blk.call(@service_cluster.properties[@nodes[hashid]])
|
445
|
+
}
|
446
|
+
}
|
447
|
+
end
|
448
|
+
|
449
|
+
private
|
450
|
+
def property_obj(hashid)
|
451
|
+
@service_cluster.properties[@nodes[hashid]]
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
|
456
|
+
class ServiceInstance
|
457
|
+
include ThreadImmutable
|
458
|
+
attr_reader :instance_id, :service_property, :agent, :service_cluster, :status_changed_at
|
459
|
+
attr_accessor :name
|
460
|
+
alias :cluster :service_cluster
|
461
|
+
alias :property :service_property
|
462
|
+
|
463
|
+
class << self
|
464
|
+
def instance_collection
|
465
|
+
@collection ||= {}
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
def initialize(service_property)
|
470
|
+
bind_thread
|
471
|
+
raise TypeError unless service_property.is_a?(Property)
|
472
|
+
|
473
|
+
@instance_id = Wakame.gen_id
|
474
|
+
@service_property = service_property
|
475
|
+
@status = Service::STATUS_OFFLINE
|
476
|
+
@status_changed_at = Time.now
|
477
|
+
|
478
|
+
self.class.instance_collection[@instance_id] = self
|
479
|
+
end
|
480
|
+
|
481
|
+
def update_status(new_status, changed_at=Time.now, fail_message=nil)
|
482
|
+
if @status != new_status
|
483
|
+
prev_status = @status
|
484
|
+
@status = new_status
|
485
|
+
@status_changed_at = changed_at
|
486
|
+
|
487
|
+
event = Event::ServiceStatusChanged.new(@instance_id, @service_property, new_status, prev_status)
|
488
|
+
event.time = @status_changed_at.dup
|
489
|
+
ED.fire_event(event)
|
490
|
+
|
491
|
+
tmp_event = nil
|
492
|
+
if prev_status != Service::STATUS_ONLINE && new_status == Service::STATUS_ONLINE
|
493
|
+
tmp_event = Event::ServiceOnline.new(self.instance_id, self.property)
|
494
|
+
tmp_event.time = @status_changed_at.dup
|
495
|
+
elsif prev_status != Service::STATUS_OFFLINE && new_status == Service::STATUS_OFFLINE
|
496
|
+
tmp_event = Event::ServiceOffline.new(self.instance_id, self.property)
|
497
|
+
tmp_event.time = @status_changed_at.dup
|
498
|
+
elsif prev_status != Service::STATUS_FAIL && new_status == Service::STATUS_FAIL
|
499
|
+
tmp_event = Event::ServiceFailed.new(self.instance_id, self.property, fail_message)
|
500
|
+
tmp_event.time = @status_changed_at.dup
|
501
|
+
end
|
502
|
+
ED.fire_event(tmp_event) if tmp_event
|
503
|
+
|
504
|
+
end
|
505
|
+
@status
|
506
|
+
end
|
507
|
+
thread_immutable_methods :update_status
|
508
|
+
|
509
|
+
|
510
|
+
def status
|
511
|
+
@status
|
512
|
+
end
|
513
|
+
|
514
|
+
def property
|
515
|
+
@service_property
|
516
|
+
end
|
517
|
+
def resource
|
518
|
+
@service_property
|
519
|
+
end
|
520
|
+
|
521
|
+
def type
|
522
|
+
@service_property.class
|
523
|
+
end
|
524
|
+
|
525
|
+
def bind_agent(agent)
|
526
|
+
return if agent.nil? || (@agent && agent.agent_id == @agent.agent_id)
|
527
|
+
raise "The agent (#{agent.agent_id}) was assigned same service already: #{property.class}" if agent.has_service_type?(property.class)
|
528
|
+
|
529
|
+
# UboundAgent & BoundAgent event occured only when the different agent obejct is assigned.
|
530
|
+
unbind_agent
|
531
|
+
@agent = agent
|
532
|
+
@agent.services[instance_id]=self
|
533
|
+
|
534
|
+
ED.fire_event(Event::ServiceBoundAgent.new(self, agent))
|
535
|
+
@agent
|
536
|
+
end
|
537
|
+
thread_immutable_methods :bind_agent
|
538
|
+
|
539
|
+
def unbind_agent
|
540
|
+
return nil if @agent.nil?
|
541
|
+
@agent.services.delete(instance_id)
|
542
|
+
old_item = @agent
|
543
|
+
@agent = nil
|
544
|
+
ED.fire_event(Event::ServiceUnboundAgent.new(self, old_item))
|
545
|
+
old_item
|
546
|
+
end
|
547
|
+
thread_immutable_methods :unbind_agent
|
548
|
+
|
549
|
+
def bind_cluster(cluster)
|
550
|
+
return if cluster.nil? || (@service_cluster && cluster.instance_id == @service_cluster.instance_id)
|
551
|
+
unbind_cluster
|
552
|
+
@service_cluster = cluster
|
553
|
+
ED.fire_event(Event::ServiceBoundCluster.new(self, cluster))
|
554
|
+
end
|
555
|
+
thread_immutable_methods :bind_cluster
|
556
|
+
|
557
|
+
def unbind_cluster
|
558
|
+
return if @service_cluster.nil?
|
559
|
+
old_item = @service_cluster
|
560
|
+
@service_cluster = nil
|
561
|
+
ED.fire_event(Event::ServiceUnboundCluster.new(self, old_item))
|
562
|
+
end
|
563
|
+
thread_immutable_methods :unbind_cluster
|
564
|
+
|
565
|
+
def export_binding
|
566
|
+
binding
|
567
|
+
end
|
568
|
+
|
569
|
+
def dump_status
|
570
|
+
ret = {:type => self.class.to_s, :status => status, :property => property.class.to_s, :instance_id => instance_id}
|
571
|
+
ret[:agent_id] = agent.agent_id if agent
|
572
|
+
ret
|
573
|
+
end
|
574
|
+
thread_immutable_methods :dump_status
|
575
|
+
|
576
|
+
def parent_instances
|
577
|
+
ary = []
|
578
|
+
@service_cluster.dg.parents(resource.class).each { |r|
|
579
|
+
@service_cluster.each_instance(r.class){ |i|
|
580
|
+
ary << i
|
581
|
+
}
|
582
|
+
}
|
583
|
+
ary.flatten
|
584
|
+
end
|
585
|
+
|
586
|
+
def child_instances
|
587
|
+
ary = []
|
588
|
+
@service_cluster.dg.children(resource.class).each { |r|
|
589
|
+
@service_cluster.each_instance(r.class){ |i|
|
590
|
+
ary << i
|
591
|
+
}
|
592
|
+
}
|
593
|
+
ary.flatten
|
594
|
+
end
|
595
|
+
end
|
596
|
+
|
597
|
+
|
598
|
+
class VmSpec
|
599
|
+
def self.define(&blk)
|
600
|
+
spec = self.new
|
601
|
+
spec.instance_eval(&blk)
|
602
|
+
spec
|
603
|
+
end
|
604
|
+
|
605
|
+
def initialize
|
606
|
+
@environments = {}
|
607
|
+
end
|
608
|
+
|
609
|
+
def current
|
610
|
+
environment(Wakame.config.environment)
|
611
|
+
end
|
612
|
+
|
613
|
+
def environment(klass_key, &blk)
|
614
|
+
envobj = @environments[klass_key]
|
615
|
+
if envobj.nil?
|
616
|
+
#klass = self.class.constants.find{ |c| c.to_s == klass_key.to_s }
|
617
|
+
if self.class.const_defined?(klass_key)
|
618
|
+
envobj = @environments[klass_key] = Wakame.new_([self.class.to_s, klass_key.to_s].join('::'))
|
619
|
+
else
|
620
|
+
raise "Undefined VM Spec template : #{klass_key}"
|
621
|
+
end
|
622
|
+
end
|
623
|
+
|
624
|
+
envobj.instance_eval(&blk) if blk
|
625
|
+
|
626
|
+
envobj
|
627
|
+
end
|
628
|
+
|
629
|
+
class Template
|
630
|
+
def self.inherited(klass)
|
631
|
+
klass.class_eval {
|
632
|
+
def self.default_attr_values
|
633
|
+
@default_attr_values ||= {}
|
634
|
+
end
|
635
|
+
def self.def_attribute(name, default_value=nil)
|
636
|
+
default_attr_values[name.to_sym]= default_value
|
637
|
+
attr_accessor(name)
|
638
|
+
end
|
639
|
+
}
|
640
|
+
end
|
641
|
+
|
642
|
+
def initialize
|
643
|
+
@attribute_keys=[]
|
644
|
+
self.class.default_attr_values.each { |n, v|
|
645
|
+
instance_variable_set("@#{n.to_s}", v)
|
646
|
+
#self.instance_eval %Q{ #{n} = #{v} }
|
647
|
+
@attribute_keys << n
|
648
|
+
}
|
649
|
+
end
|
650
|
+
|
651
|
+
def attrs
|
652
|
+
a={}
|
653
|
+
@attribute_keys.each { |k|
|
654
|
+
a[k.to_sym]=instance_variable_get("@#{k.to_s}")
|
655
|
+
}
|
656
|
+
a
|
657
|
+
end
|
658
|
+
|
659
|
+
def satisfy?(agent)
|
660
|
+
true
|
661
|
+
end
|
662
|
+
end
|
663
|
+
|
664
|
+
class EC2 < Template
|
665
|
+
AWS_VERSION=''
|
666
|
+
def_attribute :instance_type, 'm1.small'
|
667
|
+
def_attribute :availability_zone
|
668
|
+
def_attribute :key_name
|
669
|
+
def_attribute :security_groups, []
|
670
|
+
end
|
671
|
+
|
672
|
+
class StandAlone < Template
|
673
|
+
end
|
674
|
+
end
|
675
|
+
|
676
|
+
|
677
|
+
class Property
|
678
|
+
include AttributeHelper
|
679
|
+
attr_accessor :check_time, :vm_spec
|
680
|
+
def_attribute :duplicable, true
|
681
|
+
def_attribute :min_instances, 1
|
682
|
+
def_attribute :max_instances, 1
|
683
|
+
def_attribute :startup, true
|
684
|
+
def_attribute :require_agent, true
|
685
|
+
|
686
|
+
def initialize(check_time=5)
|
687
|
+
@check_time = check_time
|
688
|
+
@vm_spec = VmSpec.define {
|
689
|
+
environment(:EC2) { |ec2|
|
690
|
+
ec2.instance_type = 'm1.small'
|
691
|
+
ec2.availability_zone = 'us-east-1c'
|
692
|
+
ec2.security_groups = ['default']
|
693
|
+
}
|
694
|
+
|
695
|
+
environment(:StandAlone) {
|
696
|
+
}
|
697
|
+
}
|
698
|
+
end
|
699
|
+
|
700
|
+
def basedir
|
701
|
+
File.join(Wakame.config.root_path, 'cluster', 'resources', Util.snake_case(self.class))
|
702
|
+
end
|
703
|
+
|
704
|
+
def dump_status
|
705
|
+
{:type => self.class.to_s, :min_instances => min_instances, :max_instances=> max_instances,
|
706
|
+
:duplicable=>duplicable
|
707
|
+
}
|
708
|
+
end
|
709
|
+
|
710
|
+
def start(service_instance, action); end
|
711
|
+
def stop(service_instance, action); end
|
712
|
+
def reload(service_instance, action); end
|
713
|
+
|
714
|
+
def render_config(template)
|
715
|
+
end
|
716
|
+
|
717
|
+
#def before_start(service_instance, action)
|
718
|
+
#end
|
719
|
+
#def after_start(service_instance, action)
|
720
|
+
#end
|
721
|
+
#def before_stop(service_instance, action)
|
722
|
+
#end
|
723
|
+
#def after_stop(service_instance, action)
|
724
|
+
#end
|
725
|
+
|
726
|
+
def on_child_changed(service_instance, action)
|
727
|
+
end
|
728
|
+
def on_parent_changed(service_instance, action)
|
729
|
+
end
|
730
|
+
|
731
|
+
end
|
732
|
+
|
733
|
+
Resource = Property
|
734
|
+
end
|
735
|
+
end
|
736
|
+
|
737
|
+
module Wakame
|
738
|
+
module Service
|
739
|
+
|
740
|
+
|
741
|
+
module ApacheBasicProps
|
742
|
+
attr_accessor :listen_port, :listen_port_https, :server_root
|
743
|
+
|
744
|
+
end
|
745
|
+
|
746
|
+
class MySQL_Slave < Property
|
747
|
+
attr_reader :basedir, :mysqld_datadir, :mysqld_port, :mysqld_server_id, :mysqld_log_bin, :ebs_volume, :ebs_device
|
748
|
+
|
749
|
+
def initialize
|
750
|
+
super()
|
751
|
+
@template = ConfigurationTemplate::MySQLSlaveTemplate.new()
|
752
|
+
@basedir = '/home/wakame/mysql'
|
753
|
+
|
754
|
+
@mysqld_server_id = 2 # dynamic
|
755
|
+
@mysqld_port = 3307
|
756
|
+
@mysqld_datadir = File.expand_path('data-slave', @basedir)
|
757
|
+
|
758
|
+
@ebs_volume = 'vol-38bc5f51' # master volume_id
|
759
|
+
@ebs_device = '/dev/sdn' # slave mount point
|
760
|
+
@ebs_mount_option = 'noatime'
|
761
|
+
|
762
|
+
@mysqld_master_host = '10.249.2.115'
|
763
|
+
@mysqld_master_user = 'wakame-repl'
|
764
|
+
@mysqld_master_pass = 'wakame-slave'
|
765
|
+
@mysqld_master_port = 3306
|
766
|
+
@mysqld_master_datadir = File.expand_path('data', @basedir)
|
767
|
+
|
768
|
+
@duplicable = false
|
769
|
+
end
|
770
|
+
|
771
|
+
def before_start(svc, action)
|
772
|
+
vm_manipulator = VmManipulator.create
|
773
|
+
|
774
|
+
Wakame.log.debug("mkdir #{@mysqld_datadir}")
|
775
|
+
system("[ -d #{@mysqld_datadir} ] || mkdir -p #{@mysqld_datadir}")
|
776
|
+
Wakame.log.debug("[ -b #{@ebs_device} ]")
|
777
|
+
system("[ -b #{@ebs_device} ]")
|
778
|
+
if $? == 0
|
779
|
+
Wakame.log.debug("The EBS volume(slave) device is not ready to attach: #{@ebs_device}")
|
780
|
+
return
|
781
|
+
end
|
782
|
+
|
783
|
+
volume_map = vm_manipulator.describe_volume(@ebs_volume)
|
784
|
+
Wakame.log.debug("describe_volume(#{@ebs_volume}): #{volume_map.inspect}")
|
785
|
+
if volume_map['status'] == 'in-use'
|
786
|
+
# Nothin to be done
|
787
|
+
else
|
788
|
+
Wakame.log.debug("The EBS volume(slave) is not ready to attach: #{@ebs_volume}")
|
789
|
+
return
|
790
|
+
end
|
791
|
+
|
792
|
+
system("echo show master status | /usr/bin/mysql -h#{@mysqld_master_host} -P#{@mysqld_master_port} -u#{@mysqld_master_user} -p#{@mysqld_master_pass}")
|
793
|
+
if $? != 0
|
794
|
+
raise "Can't connect mysql master: #{@mysqld_master_host}:#{@mysqld_master_port}"
|
795
|
+
end
|
796
|
+
|
797
|
+
system("echo 'FLUSH TABLES WITH READ LOCK;' | /usr/bin/mysql -h#{@mysqld_master_host} -P#{@mysqld_master_port} -u#{@mysqld_master_user} -p#{@mysqld_master_pass} -s")
|
798
|
+
master_status = `echo show master status | /usr/bin/mysql -h#{@mysqld_master_host} -P#{@mysqld_master_port} -u#{@mysqld_master_user} -p#{@mysqld_master_pass} -s`.to_s.split(/\t/)[0..1]
|
799
|
+
# p master_status
|
800
|
+
|
801
|
+
# mysql/data/master.info
|
802
|
+
master_infos = []
|
803
|
+
master_infos << 14
|
804
|
+
master_infos << master_status[0]
|
805
|
+
master_infos << master_status[1]
|
806
|
+
master_infos << @mysqld_master_host
|
807
|
+
master_infos << @mysqld_master_user
|
808
|
+
master_infos << @mysqld_master_pass
|
809
|
+
master_infos << @mysqld_master_port
|
810
|
+
master_infos << 60
|
811
|
+
master_infos << 0
|
812
|
+
master_infos << ""
|
813
|
+
master_infos << ""
|
814
|
+
master_infos << ""
|
815
|
+
master_infos << ""
|
816
|
+
master_infos << ""
|
817
|
+
master_infos << ""
|
818
|
+
|
819
|
+
tmp_output_basedir = File.expand_path(Wakame.gen_id, "/tmp")
|
820
|
+
FileUtils.mkdir_p tmp_output_basedir
|
821
|
+
master_info = File.expand_path('master.info', tmp_output_basedir)
|
822
|
+
file = File.new(master_info, "w")
|
823
|
+
file.puts(master_infos.join("\n"))
|
824
|
+
file.chmod(0664)
|
825
|
+
file.close
|
826
|
+
|
827
|
+
3.times do |i|
|
828
|
+
system("/bin/sync")
|
829
|
+
sleep 1.0
|
830
|
+
end
|
831
|
+
|
832
|
+
Wakame.log.debug("scp -i #{Wakame.config.ssh_private_key} -o \"UserKnownHostsFile #{Wakame.config.ssh_known_hosts}\" #{master_info} root@#{@mysqld_master_host}:#{@mysqld_master_datadir}/" )
|
833
|
+
system("scp -i #{Wakame.config.ssh_private_key} -o \"UserKnownHostsFile #{Wakame.config.ssh_known_hosts}\" #{master_info} root@#{@mysqld_master_host}:#{@mysqld_master_datadir}/" )
|
834
|
+
Wakame.log.debug("ssh -i #{Wakame.config.ssh_private_key} -o \"UserKnownHostsFile #{Wakame.config.ssh_known_hosts}\" root@#{@mysqld_master_host} chown mysql:mysql #{@mysqld_master_datadir}/master.info" )
|
835
|
+
system("ssh -i #{Wakame.config.ssh_private_key} -o \"UserKnownHostsFile #{Wakame.config.ssh_known_hosts}\" root@#{@mysqld_master_host} chown mysql:mysql #{@mysqld_master_datadir}/master.info" )
|
836
|
+
|
837
|
+
3.times do |i|
|
838
|
+
system("/bin/sync")
|
839
|
+
sleep 1.0
|
840
|
+
end
|
841
|
+
|
842
|
+
FileUtils.rm_rf tmp_output_basedir
|
843
|
+
|
844
|
+
# 2. snapshot
|
845
|
+
Wakame.log.debug("create_snapshot (#{@ebs_volume})")
|
846
|
+
snapshot_map = vm_manipulator.create_snapshot(@ebs_volume)
|
847
|
+
16.times do |i|
|
848
|
+
Wakame.log.debug("describe_snapshot(#{snapshot_map.snapshotId}) ... #{i}")
|
849
|
+
snapshot_map = vm_manipulator.describe_snapshot(snapshot_map["snapshotId"])
|
850
|
+
if snapshot_map["status"] == "completed"
|
851
|
+
break
|
852
|
+
end
|
853
|
+
sleep 1.0
|
854
|
+
end
|
855
|
+
if snapshot_map["status"] != "completed"
|
856
|
+
raise "#{snapshot_map.snapshotId} status is #{snapshot_map.status}"
|
857
|
+
end
|
858
|
+
|
859
|
+
# 3. unlock mysql-master
|
860
|
+
system("echo 'UNLOCK TABLES;' | /usr/bin/mysql -h#{@mysqld_master_host} -P#{@mysqld_master_port} -u#{@mysqld_master_user} -p#{@mysqld_master_pass}")
|
861
|
+
|
862
|
+
# create volume /dev/xxxx
|
863
|
+
Wakame.log.debug("create_volume_from_snapshot(#{volume_map.availabilityZone}, #{snapshot_map.snapshotId})")
|
864
|
+
created_volume_from_snapshot_map = vm_manipulator.create_volume_from_snapshot(volume_map["availabilityZone"], snapshot_map["snapshotId"])
|
865
|
+
volume_from_snapshot_map = created_volume_from_snapshot_map
|
866
|
+
16.times do |i|
|
867
|
+
Wakame.log.debug("describe_snapshot(#{snapshot_map.snapshotId}) ... #{i}")
|
868
|
+
volume_from_snapshot_map = vm_manipulator.describe_snapshot(snapshot_map["snapshotId"])
|
869
|
+
if volume_from_snapshot_map["status"] == "completed"
|
870
|
+
break
|
871
|
+
end
|
872
|
+
sleep 1.0
|
873
|
+
end
|
874
|
+
if volume_from_snapshot_map["status"] != "completed"
|
875
|
+
raise "#{volume_from_snapshot_map.snapshotId} status is #{volume_from_snapshot_map.status}"
|
876
|
+
end
|
877
|
+
|
878
|
+
# attach volume
|
879
|
+
attach_volume_map = vm_manipulator.attach_volume(svc.agent.agent_id, created_volume_from_snapshot_map["volumeId"], @ebs_device)
|
880
|
+
16.times do |i|
|
881
|
+
Wakame.log.debug("describe_volume(#{attach_volume_map.volumeId}) ... #{i}")
|
882
|
+
attach_volume_map = vm_manipulator.describe_volume(created_volume_from_snapshot_map["volumeId"])
|
883
|
+
if attach_volume_map["status"] == "in-use"
|
884
|
+
break
|
885
|
+
end
|
886
|
+
sleep 1.0
|
887
|
+
end
|
888
|
+
if attach_volume_map["status"] != "in-use"
|
889
|
+
raise "#{attach_volume_map.volumeId} status is #{attach_volume_map.status}"
|
890
|
+
end
|
891
|
+
end
|
892
|
+
|
893
|
+
def start
|
894
|
+
mount_point_dev=`df "#{@mysqld_datadir}" | awk 'NR==2 {print $1}'`
|
895
|
+
if mount_point_dev != @ebs_device
|
896
|
+
Wakame.log.debug("Mounting EBS volume: #{@ebs_device} as #{@mysqld_datadir} (with option: #{@ebs_mount_option})")
|
897
|
+
system("/bin/mount -o #{@ebs_mount_option} #{@ebs_device} #{@mysqld_datadir}")
|
898
|
+
end
|
899
|
+
system(Wakame.config.root + "/config/init.d/mysql-slave start")
|
900
|
+
end
|
901
|
+
|
902
|
+
def check
|
903
|
+
system("/usr/bin/mysqladmin --defaults-file=/home/wakame/config/mysql-slave/my-slave.cnf ping > /dev/null")
|
904
|
+
return false if $? != 0
|
905
|
+
true
|
906
|
+
end
|
907
|
+
|
908
|
+
def stop
|
909
|
+
system(Wakame.config.root + "/config/init.d/mysql-slave stop")
|
910
|
+
end
|
911
|
+
end
|
912
|
+
|
913
|
+
end
|
914
|
+
end
|