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.
- data.tar.gz.sig +3 -0
- data/History.txt +5 -0
- data/Manifest.txt +27 -0
- data/README.txt +140 -0
- data/Rakefile +25 -0
- data/files/mysql/templates/db_slave.cnf.tmpl +12 -0
- data/files/xen_master/centos4.1 +63 -0
- data/files/xen_master/role.d/centos5-default +36 -0
- data/files/xen_master/role.d/default-edgy +36 -0
- data/files/xen_master/role.d/mysql-server-centos5 +47 -0
- data/files/xen_master/role.d/mysql-server-edgy +47 -0
- data/files/xen_master/xen-tools-centos4.conf +188 -0
- data/files/xen_master/xen-tools-centos5.conf +188 -0
- data/files/xen_master/xen-tools-edgy.conf +189 -0
- data/files/xen_master/xend-config.sxp +139 -0
- data/lib/vlad/dba/mysql.rb +445 -0
- data/lib/vlad/enterprising.rb +39 -0
- data/lib/vlad/environmentalist.rb +32 -0
- data/lib/vlad/translator.rb +138 -0
- data/lib/vlad/xen_master.rb +95 -0
- data/test/test_vlad_the_enterprising.rb +0 -0
- metadata +121 -0
- metadata.gz.sig +3 -0
@@ -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
|