snapback 0.0.1 → 0.0.3
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.
- checksums.yaml +7 -7
- data/README.md +6 -11
- data/bin/snapback +51 -67
- data/lib/snapback.rb +130 -0
- data/lib/snapback/cli/commit.rb +72 -0
- data/lib/snapback/cli/create.rb +157 -0
- data/lib/snapback/cli/drop.rb +94 -0
- data/lib/snapback/cli/install.rb +179 -0
- data/lib/snapback/cli/mount.rb +97 -0
- data/lib/snapback/cli/rollback.rb +161 -0
- data/lib/snapback/cli/snapshot.rb +155 -0
- data/lib/snapback/cli/unmount.rb +86 -0
- data/lib/snapback/configuration/Configuration_0_0_3.rb +99 -0
- data/lib/snapback/configuration_loader.rb +24 -0
- data/lib/snapback/filesystem.rb +39 -0
- data/lib/snapback/mysql/client_control.rb +125 -0
- data/lib/snapback/mysql/service_control.rb +14 -0
- data/lib/snapback/transaction.rb +25 -10
- data/lib/snapback/version.rb +3 -0
- metadata +110 -67
- data/lib/snapback/app/commit.rb +0 -35
- data/lib/snapback/app/create.rb +0 -117
- data/lib/snapback/app/drop.rb +0 -51
- data/lib/snapback/app/install.rb +0 -156
- data/lib/snapback/app/mount.rb +0 -62
- data/lib/snapback/app/rollback.rb +0 -63
- data/lib/snapback/app/snapshot.rb +0 -74
- data/lib/snapback/app/unmount.rb +0 -39
- data/lib/snapback/database.rb +0 -102
- data/lib/snapback/dsl.rb +0 -208
- data/lib/snapback/options.rb +0 -85
@@ -0,0 +1,94 @@
|
|
1
|
+
desc 'Drop an existing database'
|
2
|
+
arg_name 'database [, ...]'
|
3
|
+
command :drop do |c|
|
4
|
+
c.action do |global_options,options,args|
|
5
|
+
help_now!('database(s) required') if args.empty?
|
6
|
+
|
7
|
+
# Load the configuration
|
8
|
+
config = Snapback::ConfigurationLoader.factory global_options[:config]
|
9
|
+
|
10
|
+
# Connect to MySQL
|
11
|
+
mysql_client = config.mysql_client
|
12
|
+
|
13
|
+
args.each do |database|
|
14
|
+
|
15
|
+
# Start the transaction
|
16
|
+
Snapback::Transaction.new do
|
17
|
+
run_command "Selecting database: #{database}" do
|
18
|
+
mysql_client.database_select(database)
|
19
|
+
end
|
20
|
+
|
21
|
+
vg_name = config.lvm_volume_group
|
22
|
+
lv_name = "#{config.lvm_database_prefix}-#{database}"
|
23
|
+
lv_path = "/dev/#{vg_name}/#{lv_name}"
|
24
|
+
|
25
|
+
mount_database_directory = config.filesystem_mount_directory(database)
|
26
|
+
mysql_database_directory = "#{mysql_client.get_data_directory}/#{database}"
|
27
|
+
|
28
|
+
# Drop tablespaces
|
29
|
+
tables = run_command "Getting list of tables in database" do
|
30
|
+
mysql_client.database_tables
|
31
|
+
end
|
32
|
+
|
33
|
+
tables.each do |table|
|
34
|
+
table = table.to_s
|
35
|
+
run_command "Changing table engine to MyISAM: #{table}" do
|
36
|
+
mysql_client.table_set_engine(table, "MyISAM")
|
37
|
+
end
|
38
|
+
|
39
|
+
run_command "Dropping table: #{table}" do
|
40
|
+
mysql_client.table_drop(table)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Flush
|
45
|
+
run_command "Flush tables with read lock" do
|
46
|
+
mysql_client.flush_tables
|
47
|
+
end
|
48
|
+
|
49
|
+
# Stop MySQL
|
50
|
+
run_command "Stop MySQL server" do
|
51
|
+
Snapback::MySQL::ServiceControl.stop
|
52
|
+
end
|
53
|
+
|
54
|
+
revert do
|
55
|
+
run_command "Start MySQL server" do
|
56
|
+
Snapback::MySQL::ServiceControl.start
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
run_command "Unlinking mysql data directory",
|
61
|
+
"unlink #{mysql_database_directory}"
|
62
|
+
|
63
|
+
revert do
|
64
|
+
run_command "Linking mysql data directory",
|
65
|
+
"ln -s #{mount_database_directory} #{mysql_database_directory}"
|
66
|
+
end
|
67
|
+
|
68
|
+
# Mount the new logical volume
|
69
|
+
run_command "Unmounting logical volume",
|
70
|
+
"umount #{mount_database_directory}"
|
71
|
+
|
72
|
+
revert do
|
73
|
+
run_command "Mounting logical volume",
|
74
|
+
"mount #{lv_path} #{mount_database_directory}"
|
75
|
+
end
|
76
|
+
|
77
|
+
# Remove logical volume
|
78
|
+
run_command "Remove logical volume",
|
79
|
+
"lvremove -f #{lv_path}"
|
80
|
+
|
81
|
+
# Start MySQL
|
82
|
+
run_command "Starting MySQL server" do
|
83
|
+
Snapback::MySQL::ServiceControl.start
|
84
|
+
end
|
85
|
+
|
86
|
+
revert do
|
87
|
+
run_command "Stopping MySQL server" do
|
88
|
+
Snapback::MySQL::ServiceControl.stop
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'lvm'
|
2
|
+
require 'snapback/configuration_loader'
|
3
|
+
|
4
|
+
desc 'Ensure the environment is setup'
|
5
|
+
command :install do |c|
|
6
|
+
c.action do |global_options,options,args|
|
7
|
+
help_now!('found arguments, none expected') if !args.empty?
|
8
|
+
|
9
|
+
Snapback::Transaction.new do
|
10
|
+
|
11
|
+
puts ""
|
12
|
+
puts "Hi!"
|
13
|
+
puts ""
|
14
|
+
puts "I'm going to guide you through setting up #{"snapback".colorize(:green)}. "
|
15
|
+
puts "This script will check to see if your environment can run "
|
16
|
+
puts "Snapback and will setup configuration files for you."
|
17
|
+
puts ""
|
18
|
+
|
19
|
+
run_command "Checking LVM is installed",
|
20
|
+
"lvm version"
|
21
|
+
|
22
|
+
lvm = nil
|
23
|
+
volume_groups = nil
|
24
|
+
|
25
|
+
# Get information from LVM
|
26
|
+
run_command "Retrieving volume group information" do
|
27
|
+
lvm = LVM::LVM.new({:command => "sudo lvm", :version => "2.02.30"})
|
28
|
+
volume_groups = lvm.volume_groups.to_a
|
29
|
+
|
30
|
+
if volume_groups.size == 0 then
|
31
|
+
raise "LVM is not setup: you do not have any volume groups"
|
32
|
+
end
|
33
|
+
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
puts ""
|
38
|
+
|
39
|
+
selected_volume_group = nil
|
40
|
+
|
41
|
+
# Decide which volume group to use
|
42
|
+
if volume_groups.size == 1 then
|
43
|
+
selected_volume_group = volume_groups[0];
|
44
|
+
puts "There is one volume group available"
|
45
|
+
else
|
46
|
+
puts "There are multiple volume groups available:"
|
47
|
+
|
48
|
+
volume_groups.each_with_index.map { |volume_group, index|
|
49
|
+
puts " #{index + 1}.\t#{volume_group.name.colorize(:yellow)}"
|
50
|
+
}
|
51
|
+
|
52
|
+
puts ""
|
53
|
+
|
54
|
+
volume_group_number = ask_int "Which volume group would you like Snapback use", volume_groups.size
|
55
|
+
selected_volume_group = volume_groups[volume_group_number - 1];
|
56
|
+
end
|
57
|
+
|
58
|
+
puts "Snapback will use the volume group #{selected_volume_group.name.colorize(:green)}"
|
59
|
+
puts ""
|
60
|
+
|
61
|
+
# Check for mount directory
|
62
|
+
mysql_mount_directory = ask_string "Where do you want to mount your logical volumes [/mnt/mysql]"
|
63
|
+
mysql_mount_directory = "/mnt/mysql" if mysql_mount_directory.empty?
|
64
|
+
|
65
|
+
run_command "Changing owner to mysql: #{mysql_mount_directory}",
|
66
|
+
"chown -R mysql:mysql #{mysql_mount_directory}"
|
67
|
+
|
68
|
+
has_mysql_mount_directory = run_command "Checking for directory #{mysql_mount_directory}" do
|
69
|
+
File.directory? mysql_mount_directory
|
70
|
+
end
|
71
|
+
|
72
|
+
if !has_mysql_mount_directory then
|
73
|
+
run_command "Creating directory #{mysql_mount_directory}",
|
74
|
+
"mkdir -p #{mysql_mount_directory}"
|
75
|
+
|
76
|
+
revert do
|
77
|
+
run_command "Removing directory #{mysql_mount_directory}",
|
78
|
+
"rm -rf #{mysql_mount_directory}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# MySQL connection
|
83
|
+
mysql_client = Snapback::MySQL::ClientControl.instance
|
84
|
+
|
85
|
+
while true
|
86
|
+
puts ""
|
87
|
+
puts "Enter the credentials to connect to MySQL on localhost"
|
88
|
+
|
89
|
+
mysql_client.hostname = "localhost"
|
90
|
+
|
91
|
+
# Ask for username
|
92
|
+
mysql_client.username = ask_string "MySQL username [root]"
|
93
|
+
mysql_client.username = "root" if mysql_client.username.empty?
|
94
|
+
|
95
|
+
# Ask for password
|
96
|
+
mysql_client.password = ask_string "MySQL password"
|
97
|
+
|
98
|
+
connected = run_command "Connecting to MySQL database" do
|
99
|
+
begin
|
100
|
+
mysql_client.connect
|
101
|
+
true
|
102
|
+
rescue
|
103
|
+
false
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
if connected then
|
108
|
+
break
|
109
|
+
else
|
110
|
+
next
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# MySQL properties
|
115
|
+
|
116
|
+
has_innodb_file_per_table = run_command "Checking innodb_file_per_table is activated" do
|
117
|
+
mysql_client.has_innodb_file_per_table?
|
118
|
+
end
|
119
|
+
|
120
|
+
if !has_innodb_file_per_table then
|
121
|
+
run_command "Setting innodb_file_per_table to ON" do
|
122
|
+
mysql_client.set_innodb_file_per_table true
|
123
|
+
end
|
124
|
+
|
125
|
+
revert do
|
126
|
+
run_command "Setting innodb_file_per_table to OFF" do
|
127
|
+
mysql_client.set_innodb_file_per_table false
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
run_command "Writing configuration to file" do
|
133
|
+
config = {
|
134
|
+
'version' => Snapback::VERSION,
|
135
|
+
'lvm' => {
|
136
|
+
'volume_group' => "#{selected_volume_group.name}",
|
137
|
+
'database_prefix' => "snapback-database",
|
138
|
+
'snapshot_prefix' => "snapback-snapshot"
|
139
|
+
},
|
140
|
+
|
141
|
+
'mysql' => {
|
142
|
+
'hostname' => mysql_client.hostname,
|
143
|
+
'username' => mysql_client.username,
|
144
|
+
'password' => mysql_client.password
|
145
|
+
},
|
146
|
+
|
147
|
+
'filesystem' => {
|
148
|
+
'mount' => mysql_mount_directory
|
149
|
+
}
|
150
|
+
}
|
151
|
+
|
152
|
+
File.open(global_options[:config], 'w+') { |f| f.write(config.to_yaml) }
|
153
|
+
end
|
154
|
+
|
155
|
+
revert do
|
156
|
+
run_command "Removing configuration file" do
|
157
|
+
File.unlink global_options[:config]
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
puts ""
|
162
|
+
puts "Snapback has now been configured."
|
163
|
+
puts "To start using Snapback, run the following command: "
|
164
|
+
puts ""
|
165
|
+
puts "sudo snapback help".colorize(:yellow)
|
166
|
+
puts ""
|
167
|
+
puts "If your operating system uses AppArmor (e.g.: Ubuntu) you will need to "
|
168
|
+
puts "manually update your #{"/etc/apparmor.d/usr/sbin/mysqld".colorize(:green)} file "
|
169
|
+
puts "to include the following lines:"
|
170
|
+
puts "\t#{"/mnt/mysql/ rwk,".colorize(:green)}"
|
171
|
+
puts "\t#{"/mnt/mysql/** rwk,".colorize(:green)}"
|
172
|
+
puts ""
|
173
|
+
puts "Then manually restart AppArmor and MySQL using: "
|
174
|
+
puts "\t#{"service apparmor restart".colorize(:green)}"
|
175
|
+
puts "\t#{"service mysql restart".colorize(:green)}"
|
176
|
+
puts ""
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
desc 'Mount an existing database'
|
2
|
+
arg_name 'database [, ...]'
|
3
|
+
command :mount do |c|
|
4
|
+
c.action do |global_options,options,args|
|
5
|
+
# Ensure all flags and switches are present
|
6
|
+
help_now!('database(s) required') if args.empty?
|
7
|
+
|
8
|
+
# Load the configuration
|
9
|
+
config = Snapback::ConfigurationLoader.factory global_options[:config]
|
10
|
+
|
11
|
+
# Connect to MySQL
|
12
|
+
mysql_client = config.mysql_client
|
13
|
+
|
14
|
+
# For each database
|
15
|
+
args.each do |database|
|
16
|
+
|
17
|
+
# Start the transaction
|
18
|
+
Snapback::Transaction.new do
|
19
|
+
run_command "Selecting database: #{database}" do
|
20
|
+
mysql_client.database_select(database)
|
21
|
+
end
|
22
|
+
|
23
|
+
vg_name = config.lvm_volume_group
|
24
|
+
lv_name = config.lvm_logical_database database
|
25
|
+
lv_path = "/dev/#{vg_name}/#{lv_name}"
|
26
|
+
|
27
|
+
mount_database_directory = config.filesystem_mount_directory(database)
|
28
|
+
mysql_database_directory = "#{mysql_client.get_data_directory}/#{database}"
|
29
|
+
|
30
|
+
lv_exists = run_command "Checking logical volume exists" do
|
31
|
+
File.exists?(lv_path)
|
32
|
+
end
|
33
|
+
|
34
|
+
if !lv_exists then
|
35
|
+
raise "Logical volume #{lv_path.colorize(:red)} does not exist"
|
36
|
+
end
|
37
|
+
|
38
|
+
# Flush
|
39
|
+
run_command "Flush tables with read lock" do
|
40
|
+
mysql_client.flush_tables
|
41
|
+
end
|
42
|
+
|
43
|
+
# Stop MySQL
|
44
|
+
run_command "Stop MySQL server" do
|
45
|
+
Snapback::MySQL::ServiceControl.stop
|
46
|
+
end
|
47
|
+
|
48
|
+
revert do
|
49
|
+
run_command "Start MySQL server" do
|
50
|
+
Snapback::MySQL::ServiceControl.start
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
directory_exists = run_command "Checking if mount directory exists" do
|
55
|
+
File.directory? mount_database_directory
|
56
|
+
end
|
57
|
+
|
58
|
+
# Check mount directory exists
|
59
|
+
if !directory_exists then
|
60
|
+
run_command "Creating mount directory",
|
61
|
+
"mkdir #{mount_database_directory}"
|
62
|
+
|
63
|
+
revert do
|
64
|
+
run_command "Removing mount directory",
|
65
|
+
"rmdir #{$mount_database_directory}"
|
66
|
+
end
|
67
|
+
|
68
|
+
run_command "Changing permissions of mount directory",
|
69
|
+
"chmod 0777 #{mount_database_directory}"
|
70
|
+
end
|
71
|
+
|
72
|
+
run_command "Mounting directory",
|
73
|
+
"mount #{lv_path} #{mount_database_directory}"
|
74
|
+
|
75
|
+
run_command "Linking mount directory",
|
76
|
+
"ln -s #{mount_database_directory} #{mysql_database_directory}"
|
77
|
+
|
78
|
+
run_command "Changing ownership of: #{mount_database_directory}",
|
79
|
+
"chown -R mysql:mysql #{mount_database_directory}"
|
80
|
+
|
81
|
+
run_command "Changing ownership of: #{mysql_database_directory}",
|
82
|
+
"chown -R mysql:mysql #{mysql_database_directory}"
|
83
|
+
|
84
|
+
# Start MySQL
|
85
|
+
run_command "Start MySQL server" do
|
86
|
+
Snapback::MySQL::ServiceControl.start
|
87
|
+
end
|
88
|
+
|
89
|
+
revert do
|
90
|
+
run_command "Stop MySQL server" do
|
91
|
+
Snapback::MySQL::ServiceControl.stop
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
desc 'Rollback the working copy to the snapshot'
|
2
|
+
arg_name 'database [, ...]'
|
3
|
+
command :rollback do |c|
|
4
|
+
c.action do |global_options,options,args|
|
5
|
+
help_now!('database(s) required') if args.empty?
|
6
|
+
|
7
|
+
# Load the configuration
|
8
|
+
config = Snapback::ConfigurationLoader.factory global_options[:config]
|
9
|
+
|
10
|
+
# Connect to MySQL
|
11
|
+
mysql_client = config.mysql_client
|
12
|
+
|
13
|
+
args.each do |database|
|
14
|
+
|
15
|
+
# Start the transaction
|
16
|
+
Snapback::Transaction.new do
|
17
|
+
|
18
|
+
run_command "Selecting database: #{database}" do
|
19
|
+
mysql_client.database_select(database)
|
20
|
+
end
|
21
|
+
|
22
|
+
vg_name = config.lvm_volume_group
|
23
|
+
lv_name = "#{config.lvm_database_prefix}-#{database}"
|
24
|
+
lv_path = "/dev/#{vg_name}/#{lv_name}"
|
25
|
+
|
26
|
+
mount_database_directory = config.filesystem_mount_directory(database)
|
27
|
+
mysql_database_directory = "#{mysql_client.get_data_directory}/#{database}"
|
28
|
+
|
29
|
+
# Drop tablespaces
|
30
|
+
tables = run_command "Getting list of tables in database" do
|
31
|
+
mysql_client.database_tables
|
32
|
+
end
|
33
|
+
|
34
|
+
tables.each do |table|
|
35
|
+
table = table.to_s
|
36
|
+
run_command "Changing table engine to MyISAM: #{table}" do
|
37
|
+
mysql_client.table_set_engine(table, "MyISAM")
|
38
|
+
end
|
39
|
+
|
40
|
+
run_command "Dropping table: #{table}" do
|
41
|
+
mysql_client.table_drop(table)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Flush
|
46
|
+
run_command "Flush tables with read lock" do
|
47
|
+
mysql_client.flush_tables
|
48
|
+
end
|
49
|
+
|
50
|
+
# Stop MySQL
|
51
|
+
run_command "Stop MySQL server" do
|
52
|
+
Snapback::MySQL::ServiceControl.stop
|
53
|
+
end
|
54
|
+
|
55
|
+
revert do
|
56
|
+
run_command "Start MySQL server" do
|
57
|
+
Snapback::MySQL::ServiceControl.start
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Unlink
|
62
|
+
run_command "Unlinking mysql data directory",
|
63
|
+
"unlink #{mysql_database_directory}"
|
64
|
+
|
65
|
+
revert do
|
66
|
+
run_command "Linking mysql data directory",
|
67
|
+
"ln -s #{mount_database_directory} #{mysql_database_directory}"
|
68
|
+
end
|
69
|
+
|
70
|
+
# Unmount
|
71
|
+
run_command "Unmounting logical volume",
|
72
|
+
"umount #{mount_database_directory}"
|
73
|
+
|
74
|
+
revert do
|
75
|
+
run_command "Mounting logical volume",
|
76
|
+
"mount #{lv_path} #{mount_database_directory}"
|
77
|
+
end
|
78
|
+
|
79
|
+
# Deactivate
|
80
|
+
run_command "De-activating logical volume",
|
81
|
+
"lvchange -an #{lv_path}"
|
82
|
+
|
83
|
+
revert do
|
84
|
+
run_command "Re-activating logical volume",
|
85
|
+
"lvchange -ay #{lv_path}"
|
86
|
+
end
|
87
|
+
|
88
|
+
# Merge the old logical volume into the new one
|
89
|
+
# lvconvert --merge /dev/{vgName}/backup-{dbName}
|
90
|
+
run_command "Rolling back to the snapshot",
|
91
|
+
"lvconvert --merge /dev/#{vg_name}/#{config.lvm_snapshot_prefix}-#{database}"
|
92
|
+
|
93
|
+
# Active the master drive
|
94
|
+
run_command "Activating logical volume",
|
95
|
+
"lvchange -ay #{lv_path}"
|
96
|
+
|
97
|
+
revert do
|
98
|
+
run_command "Deactivating logical volume",
|
99
|
+
"lvchange -an #{lv_path}"
|
100
|
+
end
|
101
|
+
|
102
|
+
# Mount the master drive
|
103
|
+
run_command "Mounting logical volume",
|
104
|
+
"mount #{lv_path} #{mount_database_directory}"
|
105
|
+
|
106
|
+
revert do
|
107
|
+
run_command "Unmounting logical volume",
|
108
|
+
"umount #{mount_database_directory}"
|
109
|
+
end
|
110
|
+
|
111
|
+
# Symbolic-link the MySQL data directory to the new logical volume
|
112
|
+
run_command "Linking mysql data directory",
|
113
|
+
"ln -s #{mount_database_directory} #{mysql_database_directory}"
|
114
|
+
|
115
|
+
revert do
|
116
|
+
run_command "Unlinking mysql data directory",
|
117
|
+
"unlink #{mysql_database_directory}"
|
118
|
+
end
|
119
|
+
|
120
|
+
# Change the permissions & ownership to MySQL
|
121
|
+
run_command "Changing owner to mysql: #{mysql_database_directory}",
|
122
|
+
"chown -R mysql:mysql #{mysql_database_directory}"
|
123
|
+
|
124
|
+
run_command "Changing owner to mysql: #{mount_database_directory}",
|
125
|
+
"chown -R mysql:mysql #{mount_database_directory}"
|
126
|
+
|
127
|
+
# Start MySQL
|
128
|
+
run_command "Starting MySQL server" do
|
129
|
+
Snapback::MySQL::ServiceControl.start
|
130
|
+
end
|
131
|
+
|
132
|
+
revert do
|
133
|
+
run_command "Stopping MySQL server" do
|
134
|
+
Snapback::MySQL::ServiceControl.stop
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Reconnect
|
139
|
+
run_command "Re-connecting to MySQL" do
|
140
|
+
mysql_client.connect
|
141
|
+
end
|
142
|
+
|
143
|
+
run_command "Re-selecting database: #{database}" do
|
144
|
+
mysql_client.database_select(database)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Import tablespaces and optimize table
|
148
|
+
tables = run_command "Getting list of tables in database" do
|
149
|
+
mysql_client.database_tables
|
150
|
+
end
|
151
|
+
|
152
|
+
tables.each do |table|
|
153
|
+
table = table.to_s
|
154
|
+
run_command "Optimizing table: #{table}" do
|
155
|
+
mysql_client.table_optimize(table)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|