VladTheEnterprising 0.1.4

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.

Potentially problematic release.


This version of VladTheEnterprising might be problematic. Click here for more details.

@@ -0,0 +1,139 @@
1
+ # -*- sh -*-
2
+
3
+ #
4
+ # Xend configuration file.
5
+ #
6
+
7
+ # This example configuration is appropriate for an installation that
8
+ # utilizes a bridged network configuration. Access to xend via http
9
+ # is disabled.
10
+
11
+ # Commented out entries show the default for that entry, unless otherwise
12
+ # specified.
13
+
14
+ #(logfile /var/log/xen/xend.log)
15
+ #(loglevel DEBUG)
16
+
17
+ #(xend-http-server no)
18
+ #(xend-unix-server no)
19
+ #(xend-tcp-xmlrpc-server no)
20
+ #(xend-unix-xmlrpc-server yes)
21
+ #(xend-relocation-server no)
22
+ # The relocation server should be kept desactivated unless using a trusted
23
+ # network, the domain virtual memory will be exchanged in raw form without
24
+ # encryption of the communication. See also xend-relocation-hosts-allow option
25
+
26
+ #(xend-unix-path /var/lib/xend/xend-socket)
27
+
28
+ # Port xend should use for the HTTP interface, if xend-http-server is set.
29
+ #(xend-port 8000)
30
+
31
+ # Port xend should use for the relocation interface, if xend-relocation-server
32
+ # is set.
33
+ #(xend-relocation-port 8002)
34
+
35
+ # Address xend should listen on for HTTP connections, if xend-http-server is
36
+ # set.
37
+ # Specifying 'localhost' prevents remote connections.
38
+ # Specifying the empty string '' (the default) allows all connections.
39
+ #(xend-address '')
40
+ #(xend-address localhost)
41
+
42
+ # Address xend should listen on for relocation-socket connections, if
43
+ # xend-relocation-server is set.
44
+ # Meaning and default as for xend-address above.
45
+ #(xend-relocation-address '')
46
+
47
+ # The hosts allowed to talk to the relocation port. If this is empty (the
48
+ # default), then all connections are allowed (assuming that the connection
49
+ # arrives on a port and interface on which we are listening; see
50
+ # xend-relocation-port and xend-relocation-address above). Otherwise, this
51
+ # should be a space-separated sequence of regular expressions. Any host with
52
+ # a fully-qualified domain name or an IP address that matches one of these
53
+ # regular expressions will be accepted.
54
+ #
55
+ # For example:
56
+ # (xend-relocation-hosts-allow '^localhost$ ^.*\.example\.org$')
57
+ #
58
+ #(xend-relocation-hosts-allow '')
59
+ (xend-relocation-hosts-allow '^localhost$ ^localhost\\.localdomain$')
60
+
61
+ # The limit (in kilobytes) on the size of the console buffer
62
+ #(console-limit 1024)
63
+
64
+ ##
65
+ # To bridge network traffic, like this:
66
+ #
67
+ # dom0: fake eth0 -> vif0.0 -+
68
+ # |
69
+ # bridge -> real eth0 -> the network
70
+ # |
71
+ # domU: fake eth0 -> vifN.0 -+
72
+ #
73
+ # use
74
+ #
75
+ (network-script network-bridge)
76
+ #
77
+ # Your default ethernet device is used as the outgoing interface, by default.
78
+ # To use a different one (e.g. eth1) use
79
+ #
80
+ # (network-script 'network-bridge netdev=eth1')
81
+ #
82
+ # The bridge is named xenbr0, by default. To rename the bridge, use
83
+ #
84
+ # (network-script 'network-bridge bridge=<name>')
85
+ #
86
+ # It is possible to use the network-bridge script in more complicated
87
+ # scenarios, such as having two outgoing interfaces, with two bridges, and
88
+ # two fake interfaces per guest domain. To do things like this, write
89
+ # yourself a wrapper script, and call network-bridge from it, as appropriate.
90
+ #
91
+ #(network-script network-dummy)
92
+
93
+ # The script used to control virtual interfaces. This can be overridden on a
94
+ # per-vif basis when creating a domain or a configuring a new vif. The
95
+ # vif-bridge script is designed for use with the network-bridge script, or
96
+ # similar configurations.
97
+ #
98
+ # If you have overridden the bridge name using
99
+ # (network-script 'network-bridge bridge=<name>') then you may wish to do the
100
+ # same here. The bridge name can also be set when creating a domain or
101
+ # configuring a new vif, but a value specified here would act as a default.
102
+ #
103
+ # If you are using only one bridge, the vif-bridge script will discover that,
104
+ # so there is no need to specify it explicitly.
105
+ #
106
+ (vif-script vif-bridge)
107
+
108
+
109
+ ## Use the following if network traffic is routed, as an alternative to the
110
+ # settings for bridged networking given above.
111
+ #(network-script network-route)
112
+ #(vif-script vif-route)
113
+
114
+
115
+ ## Use the following if network traffic is routed with NAT, as an alternative
116
+ # to the settings for bridged networking given above.
117
+ #(network-script network-nat)
118
+ #(vif-script vif-nat)
119
+
120
+
121
+ # Dom0 will balloon out when needed to free memory for domU.
122
+ # dom0-min-mem is the lowest memory level (in MB) dom0 will get down to.
123
+ # If dom0-min-mem=0, dom0 will never balloon out.
124
+ (dom0-min-mem 256)
125
+
126
+ # In SMP system, dom0 will use dom0-cpus # of CPUS
127
+ # If dom0-cpus = 0, dom0 will take all cpus available
128
+ (dom0-cpus 0)
129
+
130
+ # Whether to enable core-dumps when domains crash.
131
+ #(enable-dump no)
132
+
133
+ # The tool used for initiating virtual TPM migration
134
+ #(external-migration-tool '')
135
+
136
+ # The interface for VNC servers to listen on. Defaults
137
+ # to 127.0.0.1 To restore old 'listen everywhere' behaviour
138
+ # set this to 0.0.0.0
139
+ #(vnc-listen '127.0.0.1')
@@ -0,0 +1,445 @@
1
+ require 'date'
2
+ require 'time'
3
+ require 'highline/import'
4
+ require 'monitor'
5
+ require 'resolv'
6
+ require 'vlad/translator'
7
+ require 'vlad/environmentalist'
8
+ require 'digest/md5'
9
+
10
+
11
+ namespace :vlad do
12
+ namespace :mysql do
13
+ desc "Bootstraps mysql slave candiates, installs mysql, syncs them to the master, and starts them."
14
+ task :bootstrap_new_slaves => [
15
+ :assert_production_target_subset,
16
+ :assert_dumpfile,
17
+ :assert_new_slaves,
18
+ :assert_single_master,
19
+ :ask_root_password,
20
+ :ask_replication_password,
21
+ :install_profile,
22
+ :revoke_replication,
23
+ :grant_replication,
24
+ :pre_bootstrap,
25
+ :install_mysql,
26
+ :configure_slaves,
27
+ :dump_master,
28
+ :sync_slaves,
29
+ :start_new_slaves,
30
+ :check_slaves,]
31
+
32
+
33
+ task :ask_root_password do
34
+ mysql_root_password
35
+ end
36
+
37
+ task :ask_replication_password do
38
+ mysql_replication_password
39
+ end
40
+
41
+
42
+ desc "Builds slaves configs from template, installs on slave candidates, restarts mysql on each"
43
+ task :configure_slaves => [
44
+ :assert_production_target_subset,
45
+ :assert_dumpfile,
46
+ :assert_new_slaves,
47
+ :assert_single_master,
48
+ :build_configs,
49
+ :copy_configs,
50
+ :nfs_copy_configs,
51
+ :link_config,
52
+ :configure_restart_slaves ]
53
+
54
+ task :assert_dumpfile do
55
+ if ENV["DUMPFILE"]
56
+ unless File.exist?(ENV["DUMPFILE"])
57
+ raise "DUMPFILE '#{ENV["DUMPFILE"]} doesn't exit!"
58
+ end
59
+ end
60
+ end
61
+
62
+ task :assert_production_target_subset do
63
+ if target_environment == "production"
64
+ unless defined? target_subset
65
+ raise "No target subset given, please specify a database group subset to use i.e. TARGET='staging:vendor_content'"
66
+ end
67
+ end
68
+ end
69
+
70
+ task :assert_new_slaves do
71
+ if ENV['BOOTSTRAP']
72
+ host = ENV['BOOTSTRAP']
73
+ unless Rake::RemoteTask::hosts_for(:db_slave).include?(host)
74
+ raise "Error: '#{host}' not a :db_slave in target subset '#{target_environment}:#{target_subset}'"
75
+ end
76
+ role :new_slave, ENV['BOOTSTRAP']
77
+ end
78
+ unless Rake::RemoteTask.hosts_for(:new_slave).size > 0
79
+ raise "No new slaves to bootstrap"
80
+ end
81
+ end
82
+
83
+ task :assert_single_master do
84
+ if Rake::RemoteTask.hosts_for(:db_master).size != 1
85
+ raise "Error! This task demands one and only one host have the :db_master role assigned"
86
+ end
87
+ end
88
+
89
+ remote_task :install_profile, :roles => [:db_master, :db_slave, :config_holder, :new_slave, :slave_reset_candidate ] do
90
+ if File.exist?("files/mysql/bash_profile")
91
+ `cat files/mysql/bash_profile | ssh #{target_host} "cat > .bash_profile"`
92
+ run "if [ -e .bashrc ]; then rm .bashrc; fi; ln -s .bash_profile .bashrc"
93
+ run "if [ -e .profile ]; then rm .profile; fi; ln -s .bash_profile .profile"
94
+ end
95
+ end
96
+
97
+ remote_task :grant_dump, :roles => :db_master do
98
+ slaves = Rake::RemoteTask.hosts_for(:new_slave)
99
+ slaves.each do |slave|
100
+ name = slave.gsub(/\..*$/,"").gsub(/-/, "")
101
+ mysql_query "grant all privileges on *.* to '#{name}_dump'@'#{slave}' identified by '#{mysql_replication_password}'", "", :u => "root", :p => mysql_root_password
102
+ ip = Resolv.getaddress(slave)
103
+ if ip
104
+ mysql_query "grant all privileges on *.* to '#{name}_dump'@'#{ip}' identified by '#{mysql_replication_password}'", "", :u => "root", :p => mysql_root_password
105
+ end
106
+ end
107
+ end
108
+
109
+ remote_task :grant_replication, :roles => :db_master do
110
+ slaves = Rake::RemoteTask.hosts_for(:new_slave)
111
+ slaves.each do |slave|
112
+ name = slave.gsub(/\..*$/,"").gsub(/-/, "")
113
+ mysql_query "grant replication slave, super, reload on *.* to '#{name}_repl'@'#{slave}' identified by '#{mysql_replication_password}'", "", :u => "root", :p => mysql_root_password
114
+ ip = Resolv.getaddress(slave)
115
+ if ip
116
+ mysql_query "grant replication slave, super, reload on *.* to '#{name}_repl'@'#{ip}' identified by '#{mysql_replication_password}'", "", :u => "root", :p => mysql_root_password
117
+ end
118
+ end
119
+ end
120
+
121
+ remote_task :revoke_replication, :roles => :db_master do
122
+ slaves = Rake::RemoteTask.hosts_for(:new_slave)
123
+ slaves.each do |slave|
124
+ name = slave.gsub(/\..*$/,"").gsub(/-/, "")
125
+ mysql_query "REVOKE ALL PRIVILEGES, GRANT OPTION FROM #{name}_repl", "", :u => "root", :p => mysql_root_password, :force => true
126
+ mysql_query "drop user #{name}_repl", "", :u => "root", :p => mysql_root_password, :force => true
127
+ end
128
+ end
129
+
130
+
131
+
132
+ remote_task :revoke_dump, :roles => :db_master do
133
+ slaves = Rake::RemoteTask.hosts_for(:new_slave)
134
+ slaves.each do |slave|
135
+ name = slave.gsub(/\..*$/,"").gsub(/-/, "")
136
+ mysql_query "REVOKE ALL PRIVILEGES, GRANT OPTION FROM #{name}_dump", "", :u => "root", :p => mysql_root_password, :force => true
137
+ mysql_query "drop user #{name}_dump", "", :u => "root", :p => mysql_root_password, :force => true
138
+ end
139
+ end
140
+
141
+
142
+ remote_task :set_mysql_root_password, :roles => [:new_slave] do
143
+ run "sudo su - mysql -c 'cd #{mysql_path}; ./bin/mysqladmin -u root password \"#{mysql_root_password}\"' "
144
+ run "sudo su - mysql -c 'cd #{mysql_path}; ./bin/mysqladmin -u root -h #{target_host} password \"#{mysql_root_password}\"' "
145
+ end
146
+
147
+
148
+ remote_task :copy_configs, :roles => :new_slave do
149
+ mysql_config_copy
150
+ end
151
+
152
+ remote_task :nfs_copy_configs, :roles => :config_holder do
153
+ mysql_config_nfs_copy
154
+ end
155
+
156
+
157
+ remote_task :link_config, :roles => [:new_slave] do
158
+ mysql_config_link
159
+ end
160
+
161
+ remote_task :configure_restart_slaves, :roles => [:new_slave] do
162
+ mysql_config_restart
163
+ end
164
+
165
+ remote_task :build_configs, :roles => :config_holder do
166
+ puts "Building slave configs"
167
+ slaves = Rake::RemoteTask.hosts_for(:new_slave)
168
+ slaves.each do |hostname|
169
+ name = hostname.gsub(/\..*$/,"").gsub(/-/, "")
170
+ destfile = "files/mysql/configs/#{name}.cnf"
171
+ template_file = "files/mysql/templates/#{name}.cnf.tmpl"
172
+ unless File.exist? template_file
173
+ template_file = "files/mysql/templates/db_slave.cnf.tmpl"
174
+ end
175
+ template = File.read(template_file)
176
+ server_id = Resolv.getaddress(hostname) + "-" + hostname
177
+ server_id = server_id.sum.to_s + Resolv.getaddress(hostname).gsub(/\./, "").match(/\d\d\d\d/).to_s
178
+ template.gsub!(/__SERVER_ID__/,server_id)
179
+ template.gsub!(/__HOSTNAME__/, name)
180
+ template.gsub!(/__DATADIR__/, mysql_datadir)
181
+ rstanza = ""
182
+ databases.each do |dbname|
183
+ rstanza << "replicate-do-db = #{dbname}\n"
184
+ end
185
+ template.gsub!(/__REPLICATE_DO_DB__/, rstanza)
186
+ File.open(destfile, "w") do |file|
187
+ file.write(template)
188
+ end
189
+ puts "Generated: #{destfile}"
190
+ end
191
+ end
192
+
193
+ remote_task :pre_bootstrap, :roles => [:new_slave] do
194
+ mysql_slave_pre_bootstrap
195
+ end
196
+
197
+ remote_task :install_mysql, :roles => [:new_slave] do
198
+ mysql_install
199
+ end
200
+
201
+ task :check_reset_all_slaves do
202
+ mysql_data_environments each do |group|
203
+ Kernel.fork { Kernel.exec "rake #{target_environment}:#{group} vlad:mysql:check_reset_slaves"}
204
+ Process.wait
205
+ end
206
+ end
207
+ desc "Checks that slaves are in sync, will try to start them if so."
208
+ task :check_reset_slaves => [:ask_root_password, :check_reset_each_slave ]
209
+ remote_task :check_reset_each_slave, :roles => :db_slave do
210
+ raise "Must specifiy database group type in target" unless defined? target_subset
211
+ begin
212
+ assert_slave_running
213
+ rescue
214
+ puts "#{target_host}: slave DOWN. Restarting."
215
+ begin
216
+ start_slave
217
+ sleep 15
218
+ assert_slave_running
219
+ rescue
220
+ puts "#{target_host}: restart FAILED."
221
+ end
222
+ end
223
+ end
224
+
225
+ remote_task :start_new_slaves, :roles => :new_slave do
226
+ begin
227
+ mysql_query "flush privileges; slave start;", "", :u => "root"
228
+ rescue
229
+ mysql_query "flush privileges; slave start;", "", :u => "root", :p => mysql_root_password
230
+ end
231
+ end
232
+
233
+
234
+ def start_slave
235
+ mysql_query "flush privileges; slave start;", "", :u => "root"
236
+ end
237
+
238
+ remote_task :dump_master, :roles => :db_master do
239
+ unless ENV["DUMPFILE"]
240
+ datfile = mysql_dumpfile.sub(/\.gz$/,"")
241
+ run "mkdir -p `dirname #{datfile}`; exit 0"
242
+ run "#{mysqldump} --single-transaction --master-data -uroot -p'#{mysql_root_password}' -A > #{datfile}"
243
+ `mkdir -p \`dirname #{mysql_dumpfile}\``
244
+ run "nice gzip #{datfile}"
245
+ cmd="ssh #{target_host} cat #{mysql_dumpfile} > #{mysql_dumpfile}"
246
+ puts cmd
247
+ `#{cmd}`
248
+ run "if [ -e #{mysql_dumpfile} ]; then rm #{mysql_dumpfile}; else exit 1; fi"
249
+ end
250
+ end
251
+
252
+ remote_task :sync_slaves, :roles => :new_slave do
253
+ mysql_dumpfile = ENV["DUMPFILE"] if ENV["DUMPFILE"]
254
+ run "#{mysql_path_bin}/mysql -vvf -u root -e \"slave stop\;\"; exit 0"
255
+ run "#{mysql_path_bin}/mysql -vvf -u root -e \"change master to master_host='#{mysql_master_host}', master_user='#{shortname}_repl', master_password='#{mysql_replication_password}';\""
256
+ run "mkdir -p `dirname #{mysql_dumpfile}`"
257
+ scp mysql_dumpfile, mysql_dumpfile
258
+ run "cat #{mysql_dumpfile} | gunzip - | #{mysql_path_bin}/mysql -uroot"
259
+ run "rm #{mysql_dumpfile}"
260
+ end
261
+
262
+ def assert_slave_running
263
+ cmd = "ssh #{target_host} \"#{mysql} -vvvf -uroot -p'#{mysql_root_password}' -e 'show slave status\\G' 2>/dev/null\""
264
+ output=`#{cmd}`
265
+ raise "DOWN" unless output.match(/Slave_IO_Running: Yes/)
266
+ raise "DOWN" unless output.match(/Slave_SQL_Running: Yes/)
267
+ puts "#{target_host}: slave OK"
268
+ end
269
+
270
+ def assert_agent_running
271
+ cmd = ssh #{target_host} "ps -ef | grep mysql | grep agent | grep -v grep"
272
+ puts cmd
273
+ output=`#{cmd}`
274
+ raise "DOWN" unless output.match(/mysql-service-agent/)
275
+ puts "#{target_host}: agent OK"
276
+ end
277
+
278
+ desc "shows sync status of all slaves"
279
+ remote_task :check_slaves, :roles => :db_slave do
280
+ begin
281
+ assert_slave_running
282
+ rescue Exception => e
283
+ puts "#{target_host}: slave DOWN"
284
+ end
285
+ end
286
+ task :check_slaves => [:ask_root_password]
287
+
288
+ desc "Checks mysql agent status on all slaves"
289
+ remote_task :check_restart_agents, :roles => [:db_slave, :db_master] do
290
+ cmd1 = "#{mysql_agent_init} start"
291
+ cmd2 = "#{mysql_agent_init_retry} start"
292
+ begin
293
+ assert_agent_running
294
+ rescue
295
+ begin
296
+ run cmd1
297
+ rescue
298
+ run cmd2
299
+ end
300
+ end
301
+ end
302
+
303
+ desc "checks mysql agent status on all servers"
304
+ remote_task :check_agents, :roles => [:db_slave, :db_master] do
305
+ begin
306
+ assert_agent_running
307
+ rescue Exception => e
308
+ puts "#{target_host}: agent DOWN"
309
+ end
310
+ end
311
+
312
+ desc "stops replication on all slaves"
313
+ remote_task :stop_slaves, :roles => :db_slave do
314
+ mysql_query "slave stop;", "", :u => "root", :p => mysql_root_password
315
+ end
316
+
317
+ desc "starts replication on all slaves"
318
+ remote_task :start_slaves, :roles => :db_slave do
319
+ mysql_query "flush privileges; slave start;", "", :u => "root", :p => mysql_root_password
320
+ end
321
+ desc "shows available databases"
322
+ remote_task :show_all_databases, :roles => :db_master do
323
+ puts "#{target_host}"
324
+ mysql_query "SHOW DATABASES;", "", :u => "root", :p => mysql_root_password
325
+ end
326
+ task :show_all_databases => [:ask_root_password]
327
+
328
+ remote_task :install_dot_my_cnf, :roles => :db_slave do
329
+ cnf = "[client]\n"
330
+ cnf << "host = localhost\n"
331
+ cnf << "user = root\n"
332
+ cnf << "password = #{mysql_root_password}\n"
333
+ File.open("/tmp/my.cnf.#{target_host}", "w") do |file|
334
+ file.write(cnf)
335
+ end
336
+ scp "/tmp/my.cnf.#{target_host}", ".my.cnf"
337
+ end
338
+
339
+ remote_task :remove_dot_my_cnf, :roles => :db_slave do
340
+ `rm /tmp/my.cnf.#{target_host}; exit 0`
341
+ run "rm -f .my.cnf; exit 0"
342
+ end
343
+ end
344
+ end
345
+
346
+ dialect( :name => :default_mysql,
347
+ :assert => lambda{ true },
348
+ :set => {
349
+ :mysql_master_host => lambda { Rake::RemoteTask.hosts_for(:db_master).first },
350
+ :mysql_master_ip => lambda { Resolv.getaddress(Rake::RemoteTask.fetch(mysql_master_host)) },
351
+ :mysql_stop_cmd => lambda { "sudo #{mysql_init} stop" },
352
+ :mysql_start_cmd => lambda { "sudo #{mysql_init} start" },
353
+ :mysql_safety_stop_cmd => lambda { "sudo #{mysql_init} stop; exit 0" },
354
+ :mysql_dumpfile => lambda { "dumps/#{Rake::RemoteTask::hosts_for(:db_master).first}-#{version}.dat.gz" },
355
+ :mysqldump => "mysqldump",
356
+ :mysql => "mysql",
357
+ :shortname => lambda { target_host.gsub(/\..*$/,"").gsub(/-/,"") },
358
+
359
+ })
360
+
361
+ dialect( :name => :debian_flavor_mysql,
362
+ :assert => lambda { run "apt-get -h >/dev/null 2>&1" },
363
+ :set => {
364
+ :mysql_datadir => "/var/lib/mysql",
365
+ :mysql_config_base => "/etc/mysql/",
366
+ :mysql_path_bin => "/usr/bin",
367
+ :mysql_err => "/var/log/mysql.err",
368
+ :my_cnf => lambda { "/etc/mysql/conf.d/#{shortname}.cnf" },
369
+ :my_src_cnf => lambda { "files/mysql/configs/#{shortname}.cnf" },
370
+ :my_tmp_cnf => lambda { "/tmp/my.cnf-#{version}"},
371
+ :my_dest_cnf => lambda { my_cnf },
372
+ :mysql_config_nfs_copy => lambda { true },
373
+ :mysql_config_copy => lambda {
374
+ if File.exist?(my_src_cnf)
375
+ rsync my_src_cnf, my_tmp_cnf
376
+ run "sudo cp #{my_tmp_cnf} #{my_dest_cnf}"
377
+ end
378
+ },
379
+ :mysql_config_link => lambda { true
380
+
381
+ },
382
+ :mysql_config_restart => lambda {
383
+ run mysql_safety_stop_cmd
384
+ mysql_config_link
385
+ run mysql_start_cmd
386
+ },
387
+ :mysql_slave_pre_bootstrap => lambda {
388
+ run mysql_safety_stop_cmd
389
+ #run "sudo tar cvzf #{mysql_datadir}/#{version}-ibdata-backup.tar.gz #{mysql_datadir}/ib* 2>/dev/null; exit 0;"
390
+ },
391
+ :mysql_install => lambda {
392
+ run "sudo apt-get --force-yes -y install mysql-server mysql-server-5.0 mysql-common"
393
+ mysql_start_cmd
394
+ },
395
+ :mysql_init => "/etc/init.d/mysql",
396
+ })
397
+
398
+
399
+ def mysql_query *args, &b
400
+ Thread.current[:task].mysql_query(*args, &b)
401
+ end
402
+
403
+ def mysql_root_password
404
+ unless defined? current_mysql_root_password
405
+ pw = ask("Enter mysql root password: "){ |q| q.echo = "x"}
406
+ set(:current_mysql_root_password, pw)
407
+ end
408
+ current_mysql_root_password
409
+ end
410
+
411
+
412
+ def mysql_replication_password
413
+ unless defined? current_mysql_replication_password
414
+ pw = ask("Enter replication password: "){ |q| q.echo = "x"}
415
+ set(:current_mysql_replication_password, pw)
416
+ end
417
+ current_mysql_replication_password
418
+ end
419
+
420
+ class Rake::RemoteTask
421
+ def mysql_query( sql, database="", options = {})
422
+ if options[:force]
423
+ force_enabled = true
424
+ options[:force] = nil
425
+ end
426
+ if options[:p] == ""
427
+ options[:p] = nil
428
+ end
429
+ args = options.keys.collect do |key|
430
+ case key
431
+ when :p :
432
+ if options[key] && options[key] != ""
433
+ "-#{key}'#{options[key]}'"
434
+ end
435
+ when :force :
436
+ ""
437
+ else
438
+ "-#{key}'#{options[key]}'"
439
+ end
440
+ end.join " "
441
+ command = "echo \"#{sql}\" | #{mysql} #{args} #{database}"
442
+ command << "; exit 0" if force_enabled
443
+ run command
444
+ end
445
+ end