backup-remote 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +112 -0
  3. data/bin/backup-remote +5 -0
  4. data/lib/backup.rb +155 -0
  5. data/lib/backup/archive.rb +170 -0
  6. data/lib/backup/binder.rb +22 -0
  7. data/lib/backup/cleaner.rb +116 -0
  8. data/lib/backup/cli.rb +374 -0
  9. data/lib/backup/cloud_io/base.rb +41 -0
  10. data/lib/backup/cloud_io/cloud_files.rb +298 -0
  11. data/lib/backup/cloud_io/s3.rb +260 -0
  12. data/lib/backup/compressor/base.rb +35 -0
  13. data/lib/backup/compressor/bzip2.rb +39 -0
  14. data/lib/backup/compressor/custom.rb +53 -0
  15. data/lib/backup/compressor/gzip.rb +74 -0
  16. data/lib/backup/config.rb +121 -0
  17. data/lib/backup/config/dsl.rb +106 -0
  18. data/lib/backup/config/helpers.rb +143 -0
  19. data/lib/backup/database/base.rb +85 -0
  20. data/lib/backup/database/mongodb.rb +187 -0
  21. data/lib/backup/database/mysql.rb +192 -0
  22. data/lib/backup/database/openldap.rb +95 -0
  23. data/lib/backup/database/postgresql.rb +133 -0
  24. data/lib/backup/database/redis.rb +179 -0
  25. data/lib/backup/database/remote_mysql.rb +248 -0
  26. data/lib/backup/database/riak.rb +82 -0
  27. data/lib/backup/database/sqlite.rb +57 -0
  28. data/lib/backup/encryptor/base.rb +29 -0
  29. data/lib/backup/encryptor/gpg.rb +747 -0
  30. data/lib/backup/encryptor/open_ssl.rb +77 -0
  31. data/lib/backup/errors.rb +58 -0
  32. data/lib/backup/logger.rb +199 -0
  33. data/lib/backup/logger/console.rb +51 -0
  34. data/lib/backup/logger/fog_adapter.rb +29 -0
  35. data/lib/backup/logger/logfile.rb +133 -0
  36. data/lib/backup/logger/syslog.rb +116 -0
  37. data/lib/backup/model.rb +479 -0
  38. data/lib/backup/notifier/base.rb +128 -0
  39. data/lib/backup/notifier/campfire.rb +63 -0
  40. data/lib/backup/notifier/command.rb +102 -0
  41. data/lib/backup/notifier/datadog.rb +107 -0
  42. data/lib/backup/notifier/flowdock.rb +103 -0
  43. data/lib/backup/notifier/hipchat.rb +118 -0
  44. data/lib/backup/notifier/http_post.rb +117 -0
  45. data/lib/backup/notifier/mail.rb +249 -0
  46. data/lib/backup/notifier/nagios.rb +69 -0
  47. data/lib/backup/notifier/pagerduty.rb +81 -0
  48. data/lib/backup/notifier/prowl.rb +68 -0
  49. data/lib/backup/notifier/pushover.rb +74 -0
  50. data/lib/backup/notifier/ses.rb +105 -0
  51. data/lib/backup/notifier/slack.rb +148 -0
  52. data/lib/backup/notifier/twitter.rb +58 -0
  53. data/lib/backup/notifier/zabbix.rb +63 -0
  54. data/lib/backup/package.rb +55 -0
  55. data/lib/backup/packager.rb +107 -0
  56. data/lib/backup/pipeline.rb +128 -0
  57. data/lib/backup/remote/command.rb +82 -0
  58. data/lib/backup/splitter.rb +76 -0
  59. data/lib/backup/storage/base.rb +69 -0
  60. data/lib/backup/storage/cloud_files.rb +158 -0
  61. data/lib/backup/storage/cycler.rb +75 -0
  62. data/lib/backup/storage/dropbox.rb +212 -0
  63. data/lib/backup/storage/ftp.rb +112 -0
  64. data/lib/backup/storage/local.rb +64 -0
  65. data/lib/backup/storage/qiniu.rb +65 -0
  66. data/lib/backup/storage/rsync.rb +248 -0
  67. data/lib/backup/storage/s3.rb +156 -0
  68. data/lib/backup/storage/scp.rb +67 -0
  69. data/lib/backup/storage/sftp.rb +82 -0
  70. data/lib/backup/syncer/base.rb +70 -0
  71. data/lib/backup/syncer/cloud/base.rb +179 -0
  72. data/lib/backup/syncer/cloud/cloud_files.rb +83 -0
  73. data/lib/backup/syncer/cloud/local_file.rb +100 -0
  74. data/lib/backup/syncer/cloud/s3.rb +110 -0
  75. data/lib/backup/syncer/rsync/base.rb +54 -0
  76. data/lib/backup/syncer/rsync/local.rb +31 -0
  77. data/lib/backup/syncer/rsync/pull.rb +51 -0
  78. data/lib/backup/syncer/rsync/push.rb +205 -0
  79. data/lib/backup/template.rb +46 -0
  80. data/lib/backup/utilities.rb +224 -0
  81. data/lib/backup/version.rb +5 -0
  82. data/templates/cli/archive +28 -0
  83. data/templates/cli/compressor/bzip2 +4 -0
  84. data/templates/cli/compressor/custom +7 -0
  85. data/templates/cli/compressor/gzip +4 -0
  86. data/templates/cli/config +123 -0
  87. data/templates/cli/databases/mongodb +15 -0
  88. data/templates/cli/databases/mysql +18 -0
  89. data/templates/cli/databases/openldap +24 -0
  90. data/templates/cli/databases/postgresql +16 -0
  91. data/templates/cli/databases/redis +16 -0
  92. data/templates/cli/databases/riak +17 -0
  93. data/templates/cli/databases/sqlite +11 -0
  94. data/templates/cli/encryptor/gpg +27 -0
  95. data/templates/cli/encryptor/openssl +9 -0
  96. data/templates/cli/model +26 -0
  97. data/templates/cli/notifier/zabbix +15 -0
  98. data/templates/cli/notifiers/campfire +12 -0
  99. data/templates/cli/notifiers/command +32 -0
  100. data/templates/cli/notifiers/datadog +57 -0
  101. data/templates/cli/notifiers/flowdock +16 -0
  102. data/templates/cli/notifiers/hipchat +16 -0
  103. data/templates/cli/notifiers/http_post +32 -0
  104. data/templates/cli/notifiers/mail +24 -0
  105. data/templates/cli/notifiers/nagios +13 -0
  106. data/templates/cli/notifiers/pagerduty +12 -0
  107. data/templates/cli/notifiers/prowl +11 -0
  108. data/templates/cli/notifiers/pushover +11 -0
  109. data/templates/cli/notifiers/ses +15 -0
  110. data/templates/cli/notifiers/slack +22 -0
  111. data/templates/cli/notifiers/twitter +13 -0
  112. data/templates/cli/splitter +7 -0
  113. data/templates/cli/storages/cloud_files +11 -0
  114. data/templates/cli/storages/dropbox +20 -0
  115. data/templates/cli/storages/ftp +13 -0
  116. data/templates/cli/storages/local +8 -0
  117. data/templates/cli/storages/qiniu +12 -0
  118. data/templates/cli/storages/rsync +17 -0
  119. data/templates/cli/storages/s3 +16 -0
  120. data/templates/cli/storages/scp +15 -0
  121. data/templates/cli/storages/sftp +15 -0
  122. data/templates/cli/syncers/cloud_files +22 -0
  123. data/templates/cli/syncers/rsync_local +20 -0
  124. data/templates/cli/syncers/rsync_pull +28 -0
  125. data/templates/cli/syncers/rsync_push +28 -0
  126. data/templates/cli/syncers/s3 +27 -0
  127. data/templates/general/links +3 -0
  128. data/templates/general/version.erb +2 -0
  129. data/templates/notifier/mail/failure.erb +16 -0
  130. data/templates/notifier/mail/success.erb +16 -0
  131. data/templates/notifier/mail/warning.erb +16 -0
  132. data/templates/storage/dropbox/authorization_url.erb +6 -0
  133. data/templates/storage/dropbox/authorized.erb +4 -0
  134. data/templates/storage/dropbox/cache_file_written.erb +10 -0
  135. metadata +1122 -0
@@ -0,0 +1,95 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Database
5
+ class OpenLDAP < Base
6
+ class Error < Backup::Error; end
7
+
8
+ ##
9
+ # Name of the ldap backup
10
+ attr_accessor :name
11
+
12
+ ##
13
+ # run slapcat under sudo if needed
14
+ # make sure to set SUID on a file, to let you run the file with permissions of file owner
15
+ # eg. sudo chmod u+s /usr/sbin/slapcat
16
+ attr_accessor :use_sudo
17
+
18
+ ##
19
+ # Stores the location of the slapd.conf or slapcat confdir
20
+ attr_accessor :slapcat_conf
21
+
22
+ ##
23
+ # Additional slapcat options
24
+ attr_accessor :slapcat_args
25
+
26
+ ##
27
+ # Path to slapcat utility (optional)
28
+ attr_accessor :slapcat_utility
29
+
30
+ ##
31
+ # Takes the name of the archive and the configuration block
32
+ def initialize(model, database_id = nil, &block)
33
+ super
34
+ instance_eval(&block) if block_given?
35
+
36
+ @name ||= 'ldap_backup'
37
+ @use_sudo ||= false
38
+ @slapcat_args ||= Array.new
39
+ @slapcat_utility ||= utility(:slapcat)
40
+ @slapcat_conf ||= '/etc/ldap/slapd.d'
41
+ end
42
+
43
+ ##
44
+ # Performs the slapcat command and outputs the
45
+ # data to the specified path based on the 'trigger'
46
+ def perform!
47
+ super
48
+
49
+ pipeline = Pipeline.new
50
+ dump_ext = 'ldif'
51
+
52
+ pipeline << slapcat
53
+ if @model.compressor
54
+ @model.compressor.compress_with do |command, ext|
55
+ pipeline << command
56
+ dump_ext << ext
57
+ end
58
+ end
59
+
60
+ pipeline << "#{ utility(:cat) } > " +
61
+ "'#{ File.join(dump_path, dump_filename) }.#{ dump_ext }'"
62
+
63
+ pipeline.run
64
+ if pipeline.success?
65
+ log!(:finished)
66
+ else
67
+ raise Error, "Dump Failed!\n" + pipeline.error_messages
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ ##
74
+ # Builds the full slapcat string based on all attributes
75
+ def slapcat
76
+ command = "#{ slapcat_utility } #{ slapcat_conf_option } #{ slapcat_conf } #{ user_options }"
77
+ command.prepend("sudo ") if use_sudo
78
+ command
79
+ end
80
+
81
+ ##
82
+ # Uses different slapcat switch depending on confdir or conffile set
83
+ def slapcat_conf_option
84
+ @slapcat_conf.include?(".d") ? "-F" : "-f"
85
+ end
86
+
87
+ ##
88
+ # Builds a compatible string for the additional options
89
+ # specified by the user
90
+ def user_options
91
+ slapcat_args.join(' ')
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,133 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Database
5
+ class PostgreSQL < Base
6
+ class Error < Backup::Error; end
7
+
8
+ ##
9
+ # Name of the database that needs to get dumped.
10
+ # To dump all databases, set this to `:all` or leave blank.
11
+ # +username+ must be a PostgreSQL superuser to run `pg_dumpall`.
12
+ attr_accessor :name
13
+
14
+ ##
15
+ # Credentials for the specified database
16
+ attr_accessor :username, :password
17
+
18
+ ##
19
+ # If set the pg_dump(all) command is executed as the given user
20
+ attr_accessor :sudo_user
21
+
22
+ ##
23
+ # Connectivity options
24
+ attr_accessor :host, :port, :socket
25
+
26
+ ##
27
+ # Tables to skip while dumping the database.
28
+ # If `name` is set to :all (or not specified), these are ignored.
29
+ attr_accessor :skip_tables
30
+
31
+ ##
32
+ # Tables to dump. This in only valid if `name` is specified.
33
+ # If none are given, the entire database will be dumped.
34
+ attr_accessor :only_tables
35
+
36
+ ##
37
+ # Additional "pg_dump" or "pg_dumpall" options
38
+ attr_accessor :additional_options
39
+
40
+ def initialize(model, database_id = nil, &block)
41
+ super
42
+ instance_eval(&block) if block_given?
43
+
44
+ @name ||= :all
45
+ end
46
+
47
+ ##
48
+ # Performs the pgdump command and outputs the dump file
49
+ # in the +dump_path+ using +dump_filename+.
50
+ #
51
+ # <trigger>/databases/PostgreSQL[-<database_id>].sql[.gz]
52
+ def perform!
53
+ super
54
+
55
+ pipeline = Pipeline.new
56
+ dump_ext = 'sql'
57
+
58
+ pipeline << (dump_all? ? pgdumpall : pgdump)
59
+
60
+ model.compressor.compress_with do |command, ext|
61
+ pipeline << command
62
+ dump_ext << ext
63
+ end if model.compressor
64
+
65
+ pipeline << "#{ utility(:cat) } > " +
66
+ "'#{ File.join(dump_path, dump_filename) }.#{ dump_ext }'"
67
+
68
+ pipeline.run
69
+ if pipeline.success?
70
+ log!(:finished)
71
+ else
72
+ raise Error, "Dump Failed!\n" + pipeline.error_messages
73
+ end
74
+ end
75
+
76
+ def pgdump
77
+ "#{ password_option }" +
78
+ "#{ sudo_option }" +
79
+ "#{ utility(:pg_dump) } #{ username_option } #{ connectivity_options } " +
80
+ "#{ user_options } #{ tables_to_dump } #{ tables_to_skip } #{ name }"
81
+ end
82
+
83
+ def pgdumpall
84
+ "#{ password_option }" +
85
+ "#{ sudo_option }" +
86
+ "#{ utility(:pg_dumpall) } #{ username_option } " +
87
+ "#{ connectivity_options } #{ user_options }"
88
+ end
89
+
90
+ def password_option
91
+ "PGPASSWORD=#{ Shellwords.escape(password) } " if password
92
+ end
93
+
94
+ def sudo_option
95
+ "#{ utility(:sudo) } -n -H -u #{ sudo_user } " if sudo_user
96
+ end
97
+
98
+ def username_option
99
+ "--username=#{ Shellwords.escape(username) }" if username
100
+ end
101
+
102
+ def connectivity_options
103
+ return "--host='#{ socket }'" if socket
104
+
105
+ opts = []
106
+ opts << "--host='#{ host }'" if host
107
+ opts << "--port='#{ port }'" if port
108
+ opts.join(' ')
109
+ end
110
+
111
+ def user_options
112
+ Array(additional_options).join(' ')
113
+ end
114
+
115
+ def tables_to_dump
116
+ Array(only_tables).map do |table|
117
+ "--table='#{ table }'"
118
+ end.join(' ')
119
+ end
120
+
121
+ def tables_to_skip
122
+ Array(skip_tables).map do |table|
123
+ "--exclude-table='#{ table }'"
124
+ end.join(' ')
125
+ end
126
+
127
+ def dump_all?
128
+ name == :all
129
+ end
130
+
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,179 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Database
5
+ class Redis < Base
6
+ class Error < Backup::Error; end
7
+
8
+ MODES = [:copy, :sync]
9
+
10
+ ##
11
+ # Mode of operation.
12
+ #
13
+ # [:copy]
14
+ # Copies the redis dump file specified by {#rdb_path}.
15
+ # This data will be current as of the last RDB Snapshot
16
+ # performed by the server (per your redis.conf settings).
17
+ # You may set {#invoke_save} to +true+ to have Backup issue
18
+ # a +SAVE+ command to update the dump file with the current
19
+ # data before performing the copy.
20
+ #
21
+ # [:sync]
22
+ # Performs a dump of your redis data using +redis-cli --rdb -+.
23
+ # Redis implements this internally using a +SYNC+ command.
24
+ # The operation is analogous to requesting a +BGSAVE+, then having the
25
+ # dump returned. This mode is capable of dumping data from a local or
26
+ # remote server. Requires Redis v2.6 or better.
27
+ #
28
+ # Defaults to +:copy+.
29
+ attr_accessor :mode
30
+
31
+ ##
32
+ # Full path to the redis dump file.
33
+ #
34
+ # Required when {#mode} is +:copy+.
35
+ attr_accessor :rdb_path
36
+
37
+ ##
38
+ # Perform a +SAVE+ command using the +redis-cli+ utility
39
+ # before copying the dump file specified by {#rdb_path}.
40
+ #
41
+ # Only valid when {#mode} is +:copy+.
42
+ attr_accessor :invoke_save
43
+
44
+ ##
45
+ # Connectivity options for the +redis-cli+ utility.
46
+ attr_accessor :host, :port, :socket
47
+
48
+ ##
49
+ # Password for the +redis-cli+ utility.
50
+ attr_accessor :password
51
+
52
+ ##
53
+ # Additional options for the +redis-cli+ utility.
54
+ attr_accessor :additional_options
55
+
56
+ def initialize(model, database_id = nil, &block)
57
+ super
58
+ instance_eval(&block) if block_given?
59
+
60
+ @mode ||= :copy
61
+
62
+ unless MODES.include?(mode)
63
+ raise Error, "'#{ mode }' is not a valid mode"
64
+ end
65
+
66
+ if mode == :copy && rdb_path.nil?
67
+ raise Error, '`rdb_path` must be set when `mode` is :copy'
68
+ end
69
+ end
70
+
71
+ ##
72
+ # Performs the dump based on {#mode} and stores the Redis dump file
73
+ # to the +dump_path+ using the +dump_filename+.
74
+ #
75
+ # <trigger>/databases/Redis[-<database_id>].rdb[.gz]
76
+ def perform!
77
+ super
78
+
79
+ case mode
80
+ when :sync
81
+ # messages output by `redis-cli --rdb` on $stderr
82
+ Logger.configure do
83
+ ignore_warning(/Transfer finished with success/)
84
+ ignore_warning(/SYNC sent to master/)
85
+ end
86
+ sync!
87
+ when :copy
88
+ save! if invoke_save
89
+ copy!
90
+ end
91
+
92
+ log!(:finished)
93
+ end
94
+
95
+ private
96
+
97
+ def sync!
98
+ pipeline = Pipeline.new
99
+ dump_ext = 'rdb'
100
+
101
+ pipeline << "#{ redis_cli_cmd } --rdb -"
102
+
103
+ model.compressor.compress_with do |command, ext|
104
+ pipeline << command
105
+ dump_ext << ext
106
+ end if model.compressor
107
+
108
+ pipeline << "#{ utility(:cat) } > " +
109
+ "'#{ File.join(dump_path, dump_filename) }.#{ dump_ext }'"
110
+
111
+ pipeline.run
112
+
113
+ unless pipeline.success?
114
+ raise Error, "Dump Failed!\n" + pipeline.error_messages
115
+ end
116
+ end
117
+
118
+ def save!
119
+ resp = run("#{ redis_cli_cmd } SAVE")
120
+ unless resp =~ /OK$/
121
+ raise Error, <<-EOS
122
+ Failed to invoke the `SAVE` command
123
+ Response was: #{ resp }
124
+ EOS
125
+ end
126
+
127
+ rescue Error
128
+ if resp =~ /save already in progress/
129
+ unless (attempts ||= '0').next! == '5'
130
+ sleep 5
131
+ retry
132
+ end
133
+ end
134
+ raise
135
+ end
136
+
137
+ def copy!
138
+ unless File.exist?(rdb_path)
139
+ raise Error, <<-EOS
140
+ Redis database dump not found
141
+ `rdb_path` was '#{ rdb_path }'
142
+ EOS
143
+ end
144
+
145
+ dst_path = File.join(dump_path, dump_filename + '.rdb')
146
+ if model.compressor
147
+ model.compressor.compress_with do |command, ext|
148
+ run("#{ command } -c '#{ rdb_path }' > '#{ dst_path + ext }'")
149
+ end
150
+ else
151
+ FileUtils.cp(rdb_path, dst_path)
152
+ end
153
+ end
154
+
155
+ def redis_cli_cmd
156
+ "#{ utility('redis-cli') } #{ password_option } " +
157
+ "#{ connectivity_options } #{ user_options }"
158
+ end
159
+
160
+ def password_option
161
+ "-a '#{ password }'" if password
162
+ end
163
+
164
+ def connectivity_options
165
+ return "-s '#{ socket }'" if socket
166
+
167
+ opts = []
168
+ opts << "-h '#{ host }'" if host
169
+ opts << "-p '#{ port }'" if port
170
+ opts.join(' ')
171
+ end
172
+
173
+ def user_options
174
+ Array(additional_options).join(' ')
175
+ end
176
+
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,248 @@
1
+ # encoding: utf-8
2
+ require 'net/ssh'
3
+
4
+ require 'sshkit'
5
+ require 'sshkit/dsl'
6
+ require 'sshkit/sudo'
7
+
8
+
9
+ module Backup
10
+ module Database
11
+ class RemoteMySQL < Base
12
+ class Error < Backup::Error; end
13
+
14
+ include SSHKit::DSL
15
+
16
+ # server options
17
+ attr_accessor :server_host
18
+ attr_accessor :server_ssh_user
19
+ attr_accessor :server_ssh_password
20
+ attr_accessor :server_ssh_key
21
+ attr_accessor :server_backup_path
22
+
23
+
24
+ ##
25
+ # Name of the database that needs to get dumped
26
+ # To dump all databases, set this to `:all` or leave blank.
27
+ attr_accessor :name
28
+
29
+ ##
30
+ # Credentials for the specified database
31
+ attr_accessor :username, :password
32
+
33
+ ##
34
+ # Connectivity options
35
+ attr_accessor :host, :port, :socket
36
+
37
+ ##
38
+ # Tables to skip while dumping the database
39
+ #
40
+ # If `name` is set to :all (or not specified), these must include
41
+ # a database name. e.g. 'name.table'.
42
+ # If `name` is given, these may simply be table names.
43
+ attr_accessor :skip_tables
44
+
45
+ ##
46
+ # Tables to dump. This in only valid if `name` is specified.
47
+ # If none are given, the entire database will be dumped.
48
+ attr_accessor :only_tables
49
+
50
+ ##
51
+ # Additional "mysqldump" or "innobackupex (backup creation)" options
52
+ attr_accessor :additional_options
53
+
54
+ ##
55
+ # Additional innobackupex log preparation phase ("apply-logs") options
56
+ attr_accessor :prepare_options
57
+
58
+ ##
59
+ # Default is :mysqldump (which is built in MySQL and generates
60
+ # a textual SQL file), but can be changed to :innobackupex, which
61
+ # has more feasible restore times for large databases.
62
+ # See: http://www.percona.com/doc/percona-xtrabackup/
63
+ attr_accessor :backup_engine
64
+
65
+ ##
66
+ # If true (which is the default behaviour), the backup will be prepared
67
+ # after it has been successfuly created. This option is only valid if
68
+ # :backup_engine is set to :innobackupex.
69
+ attr_accessor :prepare_backup
70
+
71
+ ##
72
+ # If set the backup engine command block is executed as the given user
73
+ attr_accessor :sudo_user
74
+
75
+ ##
76
+ # If set, do not suppress innobackupdb output (useful for debugging)
77
+ attr_accessor :verbose
78
+
79
+ def initialize(model, database_id = nil, &block)
80
+ super
81
+ instance_eval(&block) if block_given?
82
+
83
+ @name ||= :all
84
+ @backup_engine ||= :mysqldump
85
+ @prepare_backup = true if @prepare_backup.nil?
86
+ end
87
+
88
+ ##
89
+ # Performs the mysqldump or innobackupex command and outputs
90
+ # the dump file in the +dump_path+ using +dump_filename+.
91
+ #
92
+ # <trigger>/databases/MySQL[-<database_id>].[sql|tar][.gz]
93
+ def perform!
94
+ super
95
+
96
+
97
+ #
98
+ pipeline = Pipeline.new
99
+ dump_ext = sql_backup? ? 'sql' : 'tar'
100
+
101
+ pipeline << sudo_option(sql_backup? ? mysqldump : innobackupex)
102
+
103
+ model.compressor.compress_with do |command, ext|
104
+ pipeline << command
105
+ dump_ext << ext
106
+ end if model.compressor
107
+
108
+ dump_remote_file = File.join('/tmp', dump_filename+"."+dump_ext)
109
+ pipeline << "#{ utility(:cat) } > '#{ dump_remote_file }'"
110
+
111
+
112
+
113
+
114
+ # generate backup on remote server
115
+ cmd_remote = pipeline.commands.join(" | ")
116
+
117
+ remote = Backup::Remote::Command.new
118
+ res_generate = remote.run_ssh_cmd(server_host, server_ssh_user, server_ssh_password, cmd_remote)
119
+
120
+ if res_generate[:res]==0
121
+ raise 'Cannot create backup on server'
122
+ end
123
+
124
+ # download backup
125
+ dump_file = File.join(dump_path, dump_filename+"."+dump_ext)
126
+
127
+ #puts "dump local: #{dump_file}"
128
+
129
+ res_download = remote.ssh_download_file(server_host, server_ssh_user, server_ssh_password, dump_remote_file, dump_file)
130
+
131
+ #puts "res: #{res_download}"
132
+
133
+ if res_download[:res]==0
134
+ raise 'Cannot download file from server'
135
+ end
136
+
137
+ #puts "pipe: #{pipeline.commands.inspect}"
138
+ #puts "cmd: #{cmd_remote}"
139
+
140
+ #exit
141
+
142
+ # download dump from server
143
+
144
+ #puts "file: #{dump_filename}"
145
+ #puts "path: #{dump_path}"
146
+
147
+ #exit
148
+
149
+ #pipeline.run
150
+ #if pipeline.success?
151
+ # log!(:finished)
152
+ #else
153
+ # raise Error, "Dump Failed!\n" + pipeline.error_messages
154
+ #end
155
+ end
156
+
157
+ private
158
+
159
+ def mysqldump
160
+ "#{ utility(:mysqldump) } #{ user_options } #{ credential_options } " +
161
+ "#{ connectivity_options } #{ name_option } " +
162
+ "#{ tables_to_dump } #{ tables_to_skip }"
163
+ end
164
+
165
+ def credential_options
166
+ opts = []
167
+ opts << "--user=#{ Shellwords.escape(username) }" if username
168
+ opts << "--password=#{ Shellwords.escape(password) }" if password
169
+ opts.join(' ')
170
+ end
171
+
172
+ def connectivity_options
173
+ return "--socket='#{ socket }'" if socket
174
+
175
+ opts = []
176
+ opts << "--host='#{ host }'" if host
177
+ opts << "--port='#{ port }'" if port
178
+ opts.join(' ')
179
+ end
180
+
181
+ def user_options
182
+ Array(additional_options).join(' ')
183
+ end
184
+
185
+ def user_prepare_options
186
+ Array(prepare_options).join(' ')
187
+ end
188
+
189
+ def name_option
190
+ dump_all? ? '--all-databases' : name
191
+ end
192
+
193
+ def tables_to_dump
194
+ Array(only_tables).join(' ') unless dump_all?
195
+ end
196
+
197
+ def tables_to_skip
198
+ Array(skip_tables).map do |table|
199
+ table = (dump_all? || table['.']) ? table : "#{ name }.#{ table }"
200
+ "--ignore-table='#{ table }'"
201
+ end.join(' ')
202
+ end
203
+
204
+ def dump_all?
205
+ name == :all
206
+ end
207
+
208
+ def sql_backup?
209
+ backup_engine.to_sym == :mysqldump
210
+ end
211
+
212
+ def innobackupex
213
+ # Creation phase
214
+ "#{ utility(:innobackupex) } #{ credential_options } " +
215
+ "#{ connectivity_options } #{ user_options } " +
216
+ "--no-timestamp #{ temp_dir } #{ quiet_option } && " +
217
+ innobackupex_prepare +
218
+ # Move files to tar-ed stream on stdout
219
+ "#{ utility(:tar) } --remove-files -cf - " +
220
+ "-C #{ File.dirname(temp_dir) } #{ File.basename(temp_dir) }"
221
+ end
222
+
223
+ def innobackupex_prepare
224
+ return "" unless @prepare_backup
225
+ # Log applying phase (prepare for restore)
226
+ "#{ utility(:innobackupex) } --apply-log #{ temp_dir } " +
227
+ "#{ user_prepare_options } #{ quiet_option } && "
228
+ end
229
+
230
+ def sudo_option(command_block)
231
+ return command_block unless sudo_user
232
+
233
+ "sudo -s -u #{ sudo_user } -- <<END_OF_SUDO\n" +
234
+ "#{command_block}\n" +
235
+ "END_OF_SUDO\n"
236
+ end
237
+
238
+ def quiet_option
239
+ verbose ? "" : " 2> /dev/null "
240
+ end
241
+
242
+ def temp_dir
243
+ File.join(dump_path, dump_filename + ".bkpdir")
244
+ end
245
+
246
+ end
247
+ end
248
+ end