snapback 0.0.1 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/snapback/app/install.rb
DELETED
@@ -1,156 +0,0 @@
|
|
1
|
-
require "lvm"
|
2
|
-
require "singleton"
|
3
|
-
|
4
|
-
module Snapback
|
5
|
-
module App
|
6
|
-
class Install
|
7
|
-
include Singleton
|
8
|
-
|
9
|
-
def go
|
10
|
-
puts ""
|
11
|
-
puts "Hi!"
|
12
|
-
puts ""
|
13
|
-
puts "I'm going to guide you through setting up Snapback."
|
14
|
-
puts "This script will check to see if your environment can run "
|
15
|
-
puts "Snapback and will setup configuration files for you."
|
16
|
-
puts ""
|
17
|
-
|
18
|
-
begin
|
19
|
-
run "Checking LVM is installed",
|
20
|
-
"lvm version"
|
21
|
-
rescue
|
22
|
-
raise "You do not have LVM installed on this computer. You cannot use snapback."
|
23
|
-
end
|
24
|
-
|
25
|
-
# Get information from LVM
|
26
|
-
lvm = LVM::LVM.new({:command => "sudo lvm", :version => "2.02.30"})
|
27
|
-
volume_groups = []
|
28
|
-
volume_group = nil
|
29
|
-
|
30
|
-
lvm.volume_groups.each do |vg|
|
31
|
-
volume_groups.push(vg)
|
32
|
-
end
|
33
|
-
puts ""
|
34
|
-
|
35
|
-
# Decide which Logical volume use to use
|
36
|
-
if volume_groups.size == 0 then
|
37
|
-
raise "You do not have any volume groups in LVM. Please setup LVM before using Snapback"
|
38
|
-
elsif volume_groups.size == 1 then
|
39
|
-
volume_group = volume_groups[0];
|
40
|
-
puts "You have one volume group named #{volume_group.name.green}."
|
41
|
-
puts "Snapback will use this logical volume."
|
42
|
-
else
|
43
|
-
puts "Here is a list of volume groups on your system:"
|
44
|
-
|
45
|
-
volume_groups.each do |vg|
|
46
|
-
puts "#{volume_groups.size}.\t#{vg.name}"
|
47
|
-
end
|
48
|
-
|
49
|
-
volume_group_number = ask_int "Which volume group would you like Snapback use", volume_groups.size
|
50
|
-
volume_group = volume_groups[volume_group_number - 1];
|
51
|
-
end
|
52
|
-
|
53
|
-
puts ""
|
54
|
-
|
55
|
-
# Check for mount directory
|
56
|
-
mysql_mount_dir = ask_string "Where do you want to mount your logical volumes [/mnt/mysql]"
|
57
|
-
puts ""
|
58
|
-
|
59
|
-
if mysql_mount_dir.empty? then
|
60
|
-
mysql_mount_dir = "/mnt/mysql"
|
61
|
-
end
|
62
|
-
|
63
|
-
if !check "Checking for directory #{mysql_mount_dir}", lambda {
|
64
|
-
File.directory? mysql_mount_dir
|
65
|
-
} then
|
66
|
-
run "Creating directory #{mysql_mount_dir}",
|
67
|
-
"mkdir -p #{mysql_mount_dir}"
|
68
|
-
|
69
|
-
on_rollback lambda {
|
70
|
-
run "Removing #{mysql_mount_dir} directory",
|
71
|
-
"rm -rf #{mysql_mount_dir}"
|
72
|
-
}
|
73
|
-
end
|
74
|
-
|
75
|
-
# MySQL connection
|
76
|
-
|
77
|
-
while true
|
78
|
-
puts ""
|
79
|
-
puts "Enter the crudentials to connect to MySQL"
|
80
|
-
|
81
|
-
$database = Snapback::Database.instance
|
82
|
-
|
83
|
-
$database.hostname = ask_string "MySQL hostname [localhost]"
|
84
|
-
if $database.hostname.empty? then
|
85
|
-
$database.hostname = "localhost"
|
86
|
-
end
|
87
|
-
|
88
|
-
$database.username = ask_string "MySQL username [root]"
|
89
|
-
if $database.username.empty? then
|
90
|
-
$database.username = "root"
|
91
|
-
end
|
92
|
-
|
93
|
-
$database.password = ask_string "MySQL password"
|
94
|
-
|
95
|
-
puts ""
|
96
|
-
|
97
|
-
begin
|
98
|
-
check "Connecting to MySQL database", lambda {
|
99
|
-
$database.connect
|
100
|
-
true
|
101
|
-
}
|
102
|
-
rescue
|
103
|
-
show_failed
|
104
|
-
next
|
105
|
-
end
|
106
|
-
|
107
|
-
break
|
108
|
-
end
|
109
|
-
|
110
|
-
if !check "Checking #{"innodb_file_per_table"} is #{"ON"}", lambda {
|
111
|
-
$database.innodb_file_per_table
|
112
|
-
} then
|
113
|
-
debug "Setting #{"innodb_file_per_table"} to #{"ON"}"
|
114
|
-
$database.set_innodb_file_per_table true
|
115
|
-
|
116
|
-
on_rollback lambda {
|
117
|
-
debug "Setting #{"innodb_file_per_table"} to #{"OFF"}"
|
118
|
-
$database.set_innodb_file_per_table false
|
119
|
-
}
|
120
|
-
end
|
121
|
-
|
122
|
-
$config = {
|
123
|
-
'lvm' => {
|
124
|
-
'volume_group' => volume_group.name.to_s,
|
125
|
-
'prefix_database' => 'snapback-active',
|
126
|
-
'prefix_backup' => 'snapback-backup'
|
127
|
-
},
|
128
|
-
|
129
|
-
'mysql' => {
|
130
|
-
'hostname' => $database.hostname,
|
131
|
-
'username' => $database.username,
|
132
|
-
'password' => $database.password
|
133
|
-
},
|
134
|
-
|
135
|
-
'filesystem' => {
|
136
|
-
'mount' => '/mnt/mysql'
|
137
|
-
}
|
138
|
-
}
|
139
|
-
|
140
|
-
File.open($options[:config], 'w+') { |f|
|
141
|
-
f.write($config.to_yaml)
|
142
|
-
}
|
143
|
-
|
144
|
-
on_rollback lambda {
|
145
|
-
File.unlink $options[:config]
|
146
|
-
}
|
147
|
-
|
148
|
-
puts ""
|
149
|
-
puts "Snapback is now installed and configured."
|
150
|
-
puts "To start using Snapback, run the following command: "
|
151
|
-
puts ""
|
152
|
-
puts "sudo snapback --help".yellow
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
data/lib/snapback/app/mount.rb
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
require "singleton"
|
2
|
-
|
3
|
-
module Snapback
|
4
|
-
module App
|
5
|
-
class Mount
|
6
|
-
include Singleton
|
7
|
-
|
8
|
-
def go
|
9
|
-
volume_group_name = "#{$config['lvm']['volume_group']}"
|
10
|
-
logical_volume_name = "#{$config['lvm']['prefix_database']}-#{$options[:database]}"
|
11
|
-
mount_dir = get_mount_dir $options[:database]
|
12
|
-
mysql_data_dir = $database.get_data_dir
|
13
|
-
|
14
|
-
exec_flush
|
15
|
-
|
16
|
-
# Stop the MySQL Server
|
17
|
-
$database.server_stop
|
18
|
-
|
19
|
-
on_rollback lambda {
|
20
|
-
$database.server_start
|
21
|
-
}
|
22
|
-
|
23
|
-
# Create a new directory for where the MySQL database can be mounted
|
24
|
-
# mkdir /mnt/mysql/{dbName};
|
25
|
-
|
26
|
-
if !File.directory? mount_dir then
|
27
|
-
run "Make mount directory",
|
28
|
-
"mkdir #{mount_dir}"
|
29
|
-
|
30
|
-
on_rollback lambda {
|
31
|
-
run "Removing mount directory",
|
32
|
-
"rmdir #{$mount_dir}"
|
33
|
-
}
|
34
|
-
|
35
|
-
run "Changing permissions of mount directory",
|
36
|
-
"chmod 0777 #{mount_dir}"
|
37
|
-
end
|
38
|
-
|
39
|
-
# # Mount the new logical volume
|
40
|
-
# mount /dev/{vgName}/mysql-{dbName} /mnt/mysql/{dbName};
|
41
|
-
exec_mount "/dev/#{volume_group_name}/#{logical_volume_name}", mount_dir
|
42
|
-
|
43
|
-
# # Symbolic-link the MySQL data directory to the new logical volume
|
44
|
-
# ln -s /mnt/mysql/{dbName} {mysql-data-dir}/{dbName}/
|
45
|
-
exec_link "#{mysql_data_dir}/#{$options[:database]}", mount_dir
|
46
|
-
|
47
|
-
# # Change the permissions & ownership to MySQL
|
48
|
-
# chown -R mysql:mysql {mysql-data-dir}/{dbName}/
|
49
|
-
# chown -R mysql:mysql /mnt/mysql/{dbName}/
|
50
|
-
exec_chown "#{mysql_data_dir}/#{$options[:database]}"
|
51
|
-
exec_chown mount_dir
|
52
|
-
|
53
|
-
# Stop the MySQL Server
|
54
|
-
$database.server_start
|
55
|
-
|
56
|
-
on_rollback lambda {
|
57
|
-
$database.server_stop
|
58
|
-
}
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
@@ -1,63 +0,0 @@
|
|
1
|
-
require "singleton"
|
2
|
-
|
3
|
-
module Snapback
|
4
|
-
module App
|
5
|
-
class Rollback
|
6
|
-
include Singleton
|
7
|
-
|
8
|
-
def go
|
9
|
-
volume_group_name = "#{$config['lvm']['volume_group']}"
|
10
|
-
logical_volume_name = "#{$config['lvm']['prefix_database']}-#{$options[:database]}"
|
11
|
-
mount_dir = get_mount_dir $options[:database]
|
12
|
-
mysql_data_dir = $database.get_data_dir
|
13
|
-
|
14
|
-
# Flush the MySQL Logs
|
15
|
-
exec_flush
|
16
|
-
|
17
|
-
# Stop the MySQL Server
|
18
|
-
$database.server_stop
|
19
|
-
|
20
|
-
on_rollback lambda {
|
21
|
-
$database.server_start
|
22
|
-
}
|
23
|
-
|
24
|
-
# Remove the symbolic link
|
25
|
-
exec_unlink "#{mysql_data_dir}/#{$options[:database]}", mount_dir
|
26
|
-
|
27
|
-
# Unmount the logical volume
|
28
|
-
exec_unmount "/dev/#{volume_group_name}/#{logical_volume_name}", mount_dir
|
29
|
-
|
30
|
-
# Deactivate the logical volume
|
31
|
-
exec_deactivate "/dev/#{volume_group_name}/#{logical_volume_name}"
|
32
|
-
|
33
|
-
# Merge the old logical volume into the new one
|
34
|
-
# lvconvert --merge /dev/{vgName}/backup-{dbName}
|
35
|
-
run "Merging the snapshot into the live logical volume",
|
36
|
-
"lvconvert --merge /dev/#{volume_group_name}/#{$config['lvm']['prefix_backup']}-#{$options[:database]}"
|
37
|
-
|
38
|
-
# Active the master drive
|
39
|
-
# lvchange -ay /dev/{vgName}/mysql-{dbName}
|
40
|
-
exec_activate "/dev/#{volume_group_name}/#{logical_volume_name}"
|
41
|
-
|
42
|
-
# Mount the logical volume
|
43
|
-
exec_mount "/dev/#{volume_group_name}/#{logical_volume_name}", mount_dir
|
44
|
-
|
45
|
-
# Symbolic-link the MySQL data directory to the new logical volume
|
46
|
-
exec_link "#{mysql_data_dir}/#{$options[:database]}", mount_dir
|
47
|
-
|
48
|
-
# Change the permissions & ownership to MySQL
|
49
|
-
# chown -R mysql:mysql {mysql-data-dir}/{dbName}/
|
50
|
-
# chown -R mysql:mysql /mnt/mysql/{dbName}/
|
51
|
-
exec_chown "#{mysql_data_dir}/#{$options[:database]}"
|
52
|
-
exec_chown "#{mount_dir}"
|
53
|
-
|
54
|
-
# Start the MySQL Server
|
55
|
-
$database.server_start
|
56
|
-
|
57
|
-
on_rollback lambda {
|
58
|
-
$database.server_stop
|
59
|
-
}
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
require "singleton"
|
2
|
-
|
3
|
-
module Snapback
|
4
|
-
module App
|
5
|
-
class Snapshot
|
6
|
-
include Singleton
|
7
|
-
|
8
|
-
def go
|
9
|
-
# Ensure we have a size parameter
|
10
|
-
if $options[:size].nil? then
|
11
|
-
raise "You must specify a size attribute. E.g.: -s 100M"
|
12
|
-
end
|
13
|
-
|
14
|
-
if !$database.db_exists?($options[:database]) then
|
15
|
-
raise "Database '#{$options[:database]}' does not exist"
|
16
|
-
end
|
17
|
-
|
18
|
-
volume_group_name = "#{$config['lvm']['volume_group']}"
|
19
|
-
logical_volume_name = "#{$config['lvm']['prefix_database']}-#{$options[:database]}"
|
20
|
-
mount_dir = get_mount_dir $options[:database]
|
21
|
-
mysql_data_dir = $database.get_data_dir
|
22
|
-
|
23
|
-
# Flush the MySQL Logs
|
24
|
-
exec_flush
|
25
|
-
|
26
|
-
# Stop the MySQL Server
|
27
|
-
$database.server_stop
|
28
|
-
|
29
|
-
on_rollback lambda {
|
30
|
-
$database.server_start
|
31
|
-
}
|
32
|
-
|
33
|
-
# Unlink
|
34
|
-
exec_unlink "#{mysql_data_dir}/#{$options[:database]}", mount_dir
|
35
|
-
|
36
|
-
# Unmount
|
37
|
-
exec_unmount "/dev/#{volume_group_name}/#{logical_volume_name}", mount_dir
|
38
|
-
|
39
|
-
# Deactivate
|
40
|
-
exec_deactivate "/dev/#{volume_group_name}/#{logical_volume_name}"
|
41
|
-
|
42
|
-
# Branch the logical volume with a snapshot
|
43
|
-
run "Snapshot the logical volume",
|
44
|
-
"lvcreate -L #{$options[:size]} -s -n #{$config['lvm']['prefix_backup']}-#{$options[:database]} /dev/#{volume_group_name}/#{logical_volume_name}"
|
45
|
-
|
46
|
-
on_rollback lambda {
|
47
|
-
run "Remove the snapshot",
|
48
|
-
"lvremove /dev/#{volume_group_name}/#{$config['lvm']['prefix_backup']}-#{$options[:database]}"
|
49
|
-
}
|
50
|
-
|
51
|
-
# Active the master drive
|
52
|
-
exec_activate "/dev/#{volume_group_name}/#{logical_volume_name}"
|
53
|
-
|
54
|
-
# Mount the master drive
|
55
|
-
exec_mount "/dev/#{volume_group_name}/#{logical_volume_name}", mount_dir
|
56
|
-
|
57
|
-
# Symbolic-link the MySQL data directory to the new logical volume
|
58
|
-
# ln -s /mnt/mysql/{dbName} {mysql-data-dir}/{dbName}/
|
59
|
-
exec_link "#{mysql_data_dir}/#{$options[:database]}", mount_dir
|
60
|
-
|
61
|
-
# Change the permissions & ownership to MySQL
|
62
|
-
exec_chown "#{mysql_data_dir}/#{$options[:database]}"
|
63
|
-
exec_chown mount_dir
|
64
|
-
|
65
|
-
# Start the MySQL Server
|
66
|
-
$database.server_start
|
67
|
-
|
68
|
-
on_rollback lambda {
|
69
|
-
$database.server_stop
|
70
|
-
}
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
data/lib/snapback/app/unmount.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
require "singleton"
|
2
|
-
|
3
|
-
module Snapback
|
4
|
-
module App
|
5
|
-
class Unmount
|
6
|
-
include Singleton
|
7
|
-
|
8
|
-
def go
|
9
|
-
volume_group_name = "#{$config['lvm']['volume_group']}"
|
10
|
-
logical_volume_name = "#{$config['lvm']['prefix_database']}-#{$options[:database]}"
|
11
|
-
mount_dir = get_mount_dir $options[:database]
|
12
|
-
mysql_data_dir = $database.get_data_dir
|
13
|
-
|
14
|
-
# Flush
|
15
|
-
exec_flush
|
16
|
-
|
17
|
-
# Stop the MySQL Server
|
18
|
-
$database.server_stop
|
19
|
-
|
20
|
-
on_rollback lambda {
|
21
|
-
$database.server_start
|
22
|
-
}
|
23
|
-
|
24
|
-
# Unlink
|
25
|
-
exec_unlink "#{mysql_data_dir}/#{$options[:database]}", mount_dir
|
26
|
-
|
27
|
-
# Unmount
|
28
|
-
exec_unmount "/dev/#{volume_group_name}/#{logical_volume_name}", mount_dir
|
29
|
-
|
30
|
-
# Start the MySQL Server
|
31
|
-
$database.server_start
|
32
|
-
|
33
|
-
on_rollback lambda {
|
34
|
-
$database.server_stop
|
35
|
-
}
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
data/lib/snapback/database.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
require 'singleton'
|
2
|
-
require 'mysql'
|
3
|
-
|
4
|
-
# ## Database functions ##
|
5
|
-
|
6
|
-
module Snapback
|
7
|
-
class Database
|
8
|
-
include Singleton
|
9
|
-
|
10
|
-
attr_accessor :hostname, :username, :password
|
11
|
-
|
12
|
-
@connection = nil
|
13
|
-
|
14
|
-
@hostname = ""
|
15
|
-
@username = ""
|
16
|
-
@password = ""
|
17
|
-
|
18
|
-
def connect
|
19
|
-
@connection = Mysql.new @hostname, @username, @password
|
20
|
-
end
|
21
|
-
|
22
|
-
def flush_lock
|
23
|
-
begin
|
24
|
-
@connection.query "FLUSH TABLES WITH READ LOCK"
|
25
|
-
end
|
26
|
-
|
27
|
-
true
|
28
|
-
end
|
29
|
-
|
30
|
-
def unlock
|
31
|
-
begin
|
32
|
-
@connection.query "UNLOCK TABLES"
|
33
|
-
end
|
34
|
-
|
35
|
-
true
|
36
|
-
end
|
37
|
-
|
38
|
-
def get_data_dir
|
39
|
-
begin
|
40
|
-
rs = @connection.query "SHOW VARIABLES LIKE 'datadir'"
|
41
|
-
rs.each_hash do |row|
|
42
|
-
return row['Value'].gsub(/\/$/, '')
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def innodb_file_per_table
|
48
|
-
begin
|
49
|
-
rs = @connection.query "SHOW VARIABLES LIKE 'innodb_file_per_table'"
|
50
|
-
rs.each_hash do |row|
|
51
|
-
return row['Value'] == "ON"
|
52
|
-
end
|
53
|
-
rescue
|
54
|
-
raise "MySQL Query failed"
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def set_innodb_file_per_table on
|
59
|
-
begin
|
60
|
-
rs = @connection.prepare "SET GLOBAL innodb_file_per_table = ?"
|
61
|
-
rs.execute(on ? 'ON' : 'OFF')
|
62
|
-
return true
|
63
|
-
rescue
|
64
|
-
raise "MySQL Query failed"
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def db_exists? database_name
|
69
|
-
sql = @connection.list_dbs database_name
|
70
|
-
sql.size == 1
|
71
|
-
end
|
72
|
-
|
73
|
-
def db_create database_name
|
74
|
-
@connection.query "CREATE DATABASE `#{Mysql.escape_string database_name}`"
|
75
|
-
true
|
76
|
-
end
|
77
|
-
|
78
|
-
def db_drop database_name
|
79
|
-
@connection.query "DROP DATABASE `#{Mysql.escape_string database_name}`"
|
80
|
-
true
|
81
|
-
end
|
82
|
-
|
83
|
-
def db_use database_name
|
84
|
-
@connection.select_db database_name
|
85
|
-
true
|
86
|
-
end
|
87
|
-
|
88
|
-
def server_stop
|
89
|
-
run "Stop MySQL server",
|
90
|
-
"service mysql stop"
|
91
|
-
true
|
92
|
-
end
|
93
|
-
|
94
|
-
def server_start
|
95
|
-
run "Start MySQL server and reconnect",
|
96
|
-
"service mysql start"
|
97
|
-
|
98
|
-
self.connect
|
99
|
-
true
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|