cm-backup 1.0.0
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 -0
- data/README.md +20 -0
- data/bin/backup +5 -0
- data/lib/backup.rb +144 -0
- data/lib/backup/archive.rb +170 -0
- data/lib/backup/binder.rb +22 -0
- data/lib/backup/cleaner.rb +116 -0
- data/lib/backup/cli.rb +374 -0
- data/lib/backup/cloud_io/base.rb +41 -0
- data/lib/backup/cloud_io/cloud_files.rb +298 -0
- data/lib/backup/cloud_io/s3.rb +260 -0
- data/lib/backup/compressor/base.rb +35 -0
- data/lib/backup/compressor/bzip2.rb +39 -0
- data/lib/backup/compressor/custom.rb +53 -0
- data/lib/backup/compressor/gzip.rb +74 -0
- data/lib/backup/config.rb +119 -0
- data/lib/backup/config/dsl.rb +103 -0
- data/lib/backup/config/helpers.rb +143 -0
- data/lib/backup/database/base.rb +85 -0
- data/lib/backup/database/mongodb.rb +187 -0
- data/lib/backup/database/mysql.rb +192 -0
- data/lib/backup/database/openldap.rb +95 -0
- data/lib/backup/database/postgresql.rb +133 -0
- data/lib/backup/database/redis.rb +179 -0
- data/lib/backup/database/riak.rb +82 -0
- data/lib/backup/database/sqlite.rb +57 -0
- data/lib/backup/encryptor/base.rb +29 -0
- data/lib/backup/encryptor/gpg.rb +747 -0
- data/lib/backup/encryptor/open_ssl.rb +77 -0
- data/lib/backup/errors.rb +58 -0
- data/lib/backup/logger.rb +199 -0
- data/lib/backup/logger/console.rb +51 -0
- data/lib/backup/logger/fog_adapter.rb +29 -0
- data/lib/backup/logger/logfile.rb +133 -0
- data/lib/backup/logger/syslog.rb +116 -0
- data/lib/backup/model.rb +479 -0
- data/lib/backup/notifier/base.rb +128 -0
- data/lib/backup/notifier/campfire.rb +63 -0
- data/lib/backup/notifier/command.rb +102 -0
- data/lib/backup/notifier/datadog.rb +107 -0
- data/lib/backup/notifier/flowdock.rb +103 -0
- data/lib/backup/notifier/hipchat.rb +118 -0
- data/lib/backup/notifier/http_post.rb +117 -0
- data/lib/backup/notifier/mail.rb +249 -0
- data/lib/backup/notifier/nagios.rb +69 -0
- data/lib/backup/notifier/pagerduty.rb +81 -0
- data/lib/backup/notifier/prowl.rb +68 -0
- data/lib/backup/notifier/pushover.rb +74 -0
- data/lib/backup/notifier/ses.rb +105 -0
- data/lib/backup/notifier/slack.rb +148 -0
- data/lib/backup/notifier/twitter.rb +58 -0
- data/lib/backup/notifier/zabbix.rb +63 -0
- data/lib/backup/package.rb +55 -0
- data/lib/backup/packager.rb +107 -0
- data/lib/backup/pipeline.rb +124 -0
- data/lib/backup/splitter.rb +76 -0
- data/lib/backup/storage/base.rb +69 -0
- data/lib/backup/storage/cloud_files.rb +158 -0
- data/lib/backup/storage/cycler.rb +75 -0
- data/lib/backup/storage/dropbox.rb +212 -0
- data/lib/backup/storage/ftp.rb +112 -0
- data/lib/backup/storage/local.rb +64 -0
- data/lib/backup/storage/qiniu.rb +65 -0
- data/lib/backup/storage/rsync.rb +248 -0
- data/lib/backup/storage/s3.rb +156 -0
- data/lib/backup/storage/scp.rb +67 -0
- data/lib/backup/storage/sftp.rb +82 -0
- data/lib/backup/syncer/base.rb +70 -0
- data/lib/backup/syncer/cloud/base.rb +179 -0
- data/lib/backup/syncer/cloud/cloud_files.rb +83 -0
- data/lib/backup/syncer/cloud/local_file.rb +100 -0
- data/lib/backup/syncer/cloud/s3.rb +110 -0
- data/lib/backup/syncer/rsync/base.rb +54 -0
- data/lib/backup/syncer/rsync/local.rb +31 -0
- data/lib/backup/syncer/rsync/pull.rb +51 -0
- data/lib/backup/syncer/rsync/push.rb +205 -0
- data/lib/backup/template.rb +46 -0
- data/lib/backup/utilities.rb +224 -0
- data/lib/backup/version.rb +5 -0
- data/templates/cli/archive +28 -0
- data/templates/cli/compressor/bzip2 +4 -0
- data/templates/cli/compressor/custom +7 -0
- data/templates/cli/compressor/gzip +4 -0
- data/templates/cli/config +123 -0
- data/templates/cli/databases/mongodb +15 -0
- data/templates/cli/databases/mysql +18 -0
- data/templates/cli/databases/openldap +24 -0
- data/templates/cli/databases/postgresql +16 -0
- data/templates/cli/databases/redis +16 -0
- data/templates/cli/databases/riak +17 -0
- data/templates/cli/databases/sqlite +11 -0
- data/templates/cli/encryptor/gpg +27 -0
- data/templates/cli/encryptor/openssl +9 -0
- data/templates/cli/model +26 -0
- data/templates/cli/notifier/zabbix +15 -0
- data/templates/cli/notifiers/campfire +12 -0
- data/templates/cli/notifiers/command +32 -0
- data/templates/cli/notifiers/datadog +57 -0
- data/templates/cli/notifiers/flowdock +16 -0
- data/templates/cli/notifiers/hipchat +16 -0
- data/templates/cli/notifiers/http_post +32 -0
- data/templates/cli/notifiers/mail +24 -0
- data/templates/cli/notifiers/nagios +13 -0
- data/templates/cli/notifiers/pagerduty +12 -0
- data/templates/cli/notifiers/prowl +11 -0
- data/templates/cli/notifiers/pushover +11 -0
- data/templates/cli/notifiers/ses +15 -0
- data/templates/cli/notifiers/slack +22 -0
- data/templates/cli/notifiers/twitter +13 -0
- data/templates/cli/splitter +7 -0
- data/templates/cli/storages/cloud_files +11 -0
- data/templates/cli/storages/dropbox +20 -0
- data/templates/cli/storages/ftp +13 -0
- data/templates/cli/storages/local +8 -0
- data/templates/cli/storages/qiniu +12 -0
- data/templates/cli/storages/rsync +17 -0
- data/templates/cli/storages/s3 +16 -0
- data/templates/cli/storages/scp +15 -0
- data/templates/cli/storages/sftp +15 -0
- data/templates/cli/syncers/cloud_files +22 -0
- data/templates/cli/syncers/rsync_local +20 -0
- data/templates/cli/syncers/rsync_pull +28 -0
- data/templates/cli/syncers/rsync_push +28 -0
- data/templates/cli/syncers/s3 +27 -0
- data/templates/general/links +3 -0
- data/templates/general/version.erb +2 -0
- data/templates/notifier/mail/failure.erb +16 -0
- data/templates/notifier/mail/success.erb +16 -0
- data/templates/notifier/mail/warning.erb +16 -0
- data/templates/storage/dropbox/authorization_url.erb +6 -0
- data/templates/storage/dropbox/authorized.erb +4 -0
- data/templates/storage/dropbox/cache_file_written.erb +10 -0
- metadata +1077 -0
@@ -0,0 +1,112 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'net/ftp'
|
3
|
+
|
4
|
+
module Backup
|
5
|
+
module Storage
|
6
|
+
class FTP < Base
|
7
|
+
include Storage::Cycler
|
8
|
+
|
9
|
+
##
|
10
|
+
# Server credentials
|
11
|
+
attr_accessor :username, :password
|
12
|
+
|
13
|
+
##
|
14
|
+
# Server IP Address and FTP port
|
15
|
+
attr_accessor :ip, :port
|
16
|
+
|
17
|
+
##
|
18
|
+
# Use passive mode?
|
19
|
+
attr_accessor :passive_mode
|
20
|
+
|
21
|
+
##
|
22
|
+
# Configure connection open and read timeouts.
|
23
|
+
# Net::FTP's open_timeout and read_timeout will both be configured using
|
24
|
+
# this setting.
|
25
|
+
# @!attribute [rw] timeout
|
26
|
+
# @param [Integer|Float]
|
27
|
+
# @return [Integer|Float]
|
28
|
+
attr_accessor :timeout
|
29
|
+
|
30
|
+
def initialize(model, storage_id = nil)
|
31
|
+
super
|
32
|
+
|
33
|
+
@port ||= 21
|
34
|
+
@path ||= 'backups'
|
35
|
+
@passive_mode ||= false
|
36
|
+
@timeout ||= nil
|
37
|
+
path.sub!(/^~\//, '')
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
##
|
43
|
+
# Establishes a connection to the remote server
|
44
|
+
#
|
45
|
+
# Note:
|
46
|
+
# Since the FTP port is defined as a constant in the Net::FTP class, and
|
47
|
+
# might be required to change by the user, we dynamically remove and
|
48
|
+
# re-add the constant with the provided port value
|
49
|
+
def connection
|
50
|
+
if Net::FTP.const_defined?(:FTP_PORT)
|
51
|
+
Net::FTP.send(:remove_const, :FTP_PORT)
|
52
|
+
end; Net::FTP.send(:const_set, :FTP_PORT, port)
|
53
|
+
|
54
|
+
Net::FTP.open(ip, username, password) do |ftp|
|
55
|
+
if timeout
|
56
|
+
ftp.open_timeout = timeout
|
57
|
+
ftp.read_timeout = timeout
|
58
|
+
end
|
59
|
+
ftp.passive = true if passive_mode
|
60
|
+
yield ftp
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def transfer!
|
65
|
+
connection do |ftp|
|
66
|
+
create_remote_path(ftp)
|
67
|
+
|
68
|
+
package.filenames.each do |filename|
|
69
|
+
src = File.join(Config.tmp_path, filename)
|
70
|
+
dest = File.join(remote_path, filename)
|
71
|
+
Logger.info "Storing '#{ ip }:#{ dest }'..."
|
72
|
+
ftp.put(src, dest)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Called by the Cycler.
|
78
|
+
# Any error raised will be logged as a warning.
|
79
|
+
def remove!(package)
|
80
|
+
Logger.info "Removing backup package dated #{ package.time }..."
|
81
|
+
|
82
|
+
remote_path = remote_path_for(package)
|
83
|
+
connection do |ftp|
|
84
|
+
package.filenames.each do |filename|
|
85
|
+
ftp.delete(File.join(remote_path, filename))
|
86
|
+
end
|
87
|
+
|
88
|
+
ftp.rmdir(remote_path)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Creates (if they don't exist yet) all the directories on the remote
|
94
|
+
# server in order to upload the backup file. Net::FTP does not support
|
95
|
+
# paths to directories that don't yet exist when creating new
|
96
|
+
# directories. Instead, we split the parts up in to an array (for each
|
97
|
+
# '/') and loop through that to create the directories one by one.
|
98
|
+
# Net::FTP raises an exception when the directory it's trying to create
|
99
|
+
# already exists, so we have rescue it
|
100
|
+
def create_remote_path(ftp)
|
101
|
+
path_parts = Array.new
|
102
|
+
remote_path.split('/').each do |path_part|
|
103
|
+
path_parts << path_part
|
104
|
+
begin
|
105
|
+
ftp.mkdir(path_parts.join('/'))
|
106
|
+
rescue Net::FTPPermError; end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Backup
|
4
|
+
module Storage
|
5
|
+
class Local < Base
|
6
|
+
include Storage::Cycler
|
7
|
+
class Error < Backup::Error; end
|
8
|
+
|
9
|
+
def initialize(model, storage_id = nil)
|
10
|
+
super
|
11
|
+
|
12
|
+
@path ||= '~/backups'
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def transfer!
|
18
|
+
FileUtils.mkdir_p(remote_path)
|
19
|
+
|
20
|
+
transfer_method = package_movable? ? :mv : :cp
|
21
|
+
package.filenames.each do |filename|
|
22
|
+
src = File.join(Config.tmp_path, filename)
|
23
|
+
dest = File.join(remote_path, filename)
|
24
|
+
Logger.info "Storing '#{ dest }'..."
|
25
|
+
|
26
|
+
FileUtils.send(transfer_method, src, dest)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Called by the Cycler.
|
31
|
+
# Any error raised will be logged as a warning.
|
32
|
+
def remove!(package)
|
33
|
+
Logger.info "Removing backup package dated #{ package.time }..."
|
34
|
+
|
35
|
+
FileUtils.rm_r(remote_path_for(package))
|
36
|
+
end
|
37
|
+
|
38
|
+
# expanded since this is a local path
|
39
|
+
def remote_path(pkg = package)
|
40
|
+
File.expand_path(super)
|
41
|
+
end
|
42
|
+
alias :remote_path_for :remote_path
|
43
|
+
|
44
|
+
##
|
45
|
+
# If this Local Storage is not the last Storage for the Model,
|
46
|
+
# force the transfer to use a *copy* operation and issue a warning.
|
47
|
+
def package_movable?
|
48
|
+
if self == model.storages.last
|
49
|
+
true
|
50
|
+
else
|
51
|
+
Logger.warn Error.new(<<-EOS)
|
52
|
+
Local File Copy Warning!
|
53
|
+
The final backup file(s) for '#{ model.label }' (#{ model.trigger })
|
54
|
+
will be *copied* to '#{ remote_path }'
|
55
|
+
To avoid this, when using more than one Storage, the 'Local' Storage
|
56
|
+
should be added *last* so the files may be *moved* to their destination.
|
57
|
+
EOS
|
58
|
+
false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'qiniu'
|
3
|
+
|
4
|
+
module Backup
|
5
|
+
module Storage
|
6
|
+
class Qiniu < Base
|
7
|
+
include Storage::Cycler
|
8
|
+
class Error < Backup::Error; end
|
9
|
+
|
10
|
+
##
|
11
|
+
# Qiniu API credentials
|
12
|
+
attr_accessor :access_key, :secret_key
|
13
|
+
|
14
|
+
##
|
15
|
+
# Qiniu bucket name
|
16
|
+
attr_accessor :bucket
|
17
|
+
|
18
|
+
def initialize(model, storage_id = nil)
|
19
|
+
super
|
20
|
+
|
21
|
+
@path ||= 'backups'
|
22
|
+
|
23
|
+
check_configuration
|
24
|
+
config_credentials
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def transfer!
|
29
|
+
package.filenames.each do |filename|
|
30
|
+
src = File.join(Config.tmp_path, filename)
|
31
|
+
dest = File.join(remote_path, filename)
|
32
|
+
Logger.info "Storing '#{ dest }'..."
|
33
|
+
|
34
|
+
::Qiniu.upload_file(uptoken: ::Qiniu.generate_upload_token,
|
35
|
+
bucket: bucket,
|
36
|
+
file: src,
|
37
|
+
key: dest)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Called by the Cycler.
|
42
|
+
# Any error raised will be logged as a warning.
|
43
|
+
def remove!(package)
|
44
|
+
Logger.info "Removing backup package dated #{ package.time }..."
|
45
|
+
remote_path = remote_path_for(package)
|
46
|
+
package.filenames.each do |filename|
|
47
|
+
::Qiniu.delete(bucket, File.join(remote_path, filename))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def check_configuration
|
52
|
+
required = %w{ access_key secret_key bucket }
|
53
|
+
|
54
|
+
raise Error, <<-EOS if required.map {|name| send(name) }.any?(&:nil?)
|
55
|
+
Configuration Error
|
56
|
+
#{ required.map {|name| "##{ name }"}.join(', ') } are all required
|
57
|
+
EOS
|
58
|
+
end
|
59
|
+
|
60
|
+
def config_credentials
|
61
|
+
::Qiniu.establish_connection!(access_key: access_key, secret_key: secret_key)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,248 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Backup
|
4
|
+
module Storage
|
5
|
+
class RSync < Base
|
6
|
+
include Utilities::Helpers
|
7
|
+
|
8
|
+
##
|
9
|
+
# Mode of operation
|
10
|
+
#
|
11
|
+
# [:ssh (default)]
|
12
|
+
# Connects to the remote via SSH.
|
13
|
+
# Does not use an rsync daemon on the remote.
|
14
|
+
#
|
15
|
+
# [:ssh_daemon]
|
16
|
+
# Connects to the remote via SSH.
|
17
|
+
# Spawns a single-use daemon on the remote, which allows certain
|
18
|
+
# daemon features (like modules) to be used.
|
19
|
+
#
|
20
|
+
# [:rsync_daemon]
|
21
|
+
# Connects directly to an rsync daemon via TCP.
|
22
|
+
# Data transferred is not encrypted.
|
23
|
+
#
|
24
|
+
attr_accessor :mode
|
25
|
+
|
26
|
+
##
|
27
|
+
# Server Address
|
28
|
+
#
|
29
|
+
# If not specified, the storage operation will be local.
|
30
|
+
attr_accessor :host
|
31
|
+
|
32
|
+
##
|
33
|
+
# SSH or RSync port
|
34
|
+
#
|
35
|
+
# For `:ssh` or `:ssh_daemon` mode, this specifies the SSH port to use
|
36
|
+
# and defaults to 22.
|
37
|
+
#
|
38
|
+
# For `:rsync_daemon` mode, this specifies the TCP port to use
|
39
|
+
# and defaults to 873.
|
40
|
+
attr_accessor :port
|
41
|
+
|
42
|
+
##
|
43
|
+
# SSH User
|
44
|
+
#
|
45
|
+
# If the user running the backup is not the same user that needs to
|
46
|
+
# authenticate with the remote server, specify the user here.
|
47
|
+
#
|
48
|
+
# The user must have SSH keys setup for passphrase-less access to the
|
49
|
+
# remote. If the SSH User does not have passphrase-less keys, or no
|
50
|
+
# default keys in their `~/.ssh` directory, you will need to use the
|
51
|
+
# `-i` option in `:additional_ssh_options` to specify the
|
52
|
+
# passphrase-less key to use.
|
53
|
+
#
|
54
|
+
# Used only for `:ssh` and `:ssh_daemon` modes.
|
55
|
+
attr_accessor :ssh_user
|
56
|
+
|
57
|
+
##
|
58
|
+
# Additional SSH Options
|
59
|
+
#
|
60
|
+
# Used to supply a String or Array of options to be passed to the SSH
|
61
|
+
# command in `:ssh` and `:ssh_daemon` modes.
|
62
|
+
#
|
63
|
+
# For example, if you need to supply a specific SSH key for the `ssh_user`,
|
64
|
+
# you would set this to: "-i '/path/to/id_rsa'". Which would produce:
|
65
|
+
#
|
66
|
+
# rsync -e "ssh -p 22 -i '/path/to/id_rsa'"
|
67
|
+
#
|
68
|
+
# Arguments may be single-quoted, but should not contain any double-quotes.
|
69
|
+
#
|
70
|
+
# Used only for `:ssh` and `:ssh_daemon` modes.
|
71
|
+
attr_accessor :additional_ssh_options
|
72
|
+
|
73
|
+
##
|
74
|
+
# RSync User
|
75
|
+
#
|
76
|
+
# If the user running the backup is not the same user that needs to
|
77
|
+
# authenticate with the rsync daemon, specify the user here.
|
78
|
+
#
|
79
|
+
# Used only for `:ssh_daemon` and `:rsync_daemon` modes.
|
80
|
+
attr_accessor :rsync_user
|
81
|
+
|
82
|
+
##
|
83
|
+
# RSync Password
|
84
|
+
#
|
85
|
+
# If specified, Backup will write the password to a temporary file and
|
86
|
+
# use it with rsync's `--password-file` option for daemon authentication.
|
87
|
+
#
|
88
|
+
# Note that setting this will override `rsync_password_file`.
|
89
|
+
#
|
90
|
+
# Used only for `:ssh_daemon` and `:rsync_daemon` modes.
|
91
|
+
attr_accessor :rsync_password
|
92
|
+
|
93
|
+
##
|
94
|
+
# RSync Password File
|
95
|
+
#
|
96
|
+
# If specified, this path will be passed to rsync's `--password-file`
|
97
|
+
# option for daemon authentication.
|
98
|
+
#
|
99
|
+
# Used only for `:ssh_daemon` and `:rsync_daemon` modes.
|
100
|
+
attr_accessor :rsync_password_file
|
101
|
+
|
102
|
+
##
|
103
|
+
# Additional String or Array of options for the rsync cli
|
104
|
+
attr_accessor :additional_rsync_options
|
105
|
+
|
106
|
+
##
|
107
|
+
# Flag for compressing (only compresses for the transfer)
|
108
|
+
attr_accessor :compress
|
109
|
+
|
110
|
+
##
|
111
|
+
# Path to store the synced backup package file(s) to.
|
112
|
+
#
|
113
|
+
# If no +host+ is specified, then +path+ will be local, and the only
|
114
|
+
# other used option would be +additional_rsync_options+.
|
115
|
+
# +path+ will be expanded, so '~/my_path' will expand to '$HOME/my_path'.
|
116
|
+
#
|
117
|
+
# If a +host+ is specified, this will be a path on the host.
|
118
|
+
# If +mode+ is `:ssh` (default), then any relative path, or path starting
|
119
|
+
# with '~/' will be relative to the directory the ssh_user is logged
|
120
|
+
# into. For `:ssh_daemon` or `:rsync_daemon` modes, this would reference
|
121
|
+
# an rsync module/path.
|
122
|
+
#
|
123
|
+
# In :ssh_daemon and :rsync_daemon modes, +path+ (or path defined by
|
124
|
+
# your rsync module) must already exist.
|
125
|
+
#
|
126
|
+
# In :ssh mode or local operation (no +host+ specified), +path+ will
|
127
|
+
# be created if needed - either locally, or on the remote for :ssh mode.
|
128
|
+
attr_accessor :path
|
129
|
+
|
130
|
+
def initialize(model, storage_id = nil)
|
131
|
+
super
|
132
|
+
|
133
|
+
@mode ||= :ssh
|
134
|
+
@port ||= mode == :rsync_daemon ? 873 : 22
|
135
|
+
@compress ||= false
|
136
|
+
@path ||= '~/backups'
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
|
141
|
+
def transfer!
|
142
|
+
write_password_file
|
143
|
+
create_remote_path
|
144
|
+
|
145
|
+
package.filenames.each do |filename|
|
146
|
+
src = "'#{ File.join(Config.tmp_path, filename) }'"
|
147
|
+
dest = "#{ host_options }'#{ File.join(remote_path, filename) }'"
|
148
|
+
Logger.info "Syncing to #{ dest }..."
|
149
|
+
run("#{ rsync_command } #{ src } #{ dest }")
|
150
|
+
end
|
151
|
+
ensure
|
152
|
+
remove_password_file
|
153
|
+
end
|
154
|
+
|
155
|
+
##
|
156
|
+
# Other storages add an additional timestamp directory to this path.
|
157
|
+
# This is not desired here, since we need to transfer the package files
|
158
|
+
# to the same location each time.
|
159
|
+
def remote_path
|
160
|
+
@remote_path ||= begin
|
161
|
+
if host
|
162
|
+
path.sub(/^~\//, '').sub(/\/$/, '')
|
163
|
+
else
|
164
|
+
File.expand_path(path)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
##
|
170
|
+
# Runs a 'mkdir -p' command on the host (or locally) to ensure the
|
171
|
+
# dest_path exists. This is used because we're transferring a single
|
172
|
+
# file, and rsync won't attempt to create the intermediate directories.
|
173
|
+
#
|
174
|
+
# This is only applicable locally and in :ssh mode.
|
175
|
+
# In :ssh_daemon and :rsync_daemon modes the `path` would include a
|
176
|
+
# module name that must define a path on the remote that already exists.
|
177
|
+
def create_remote_path
|
178
|
+
if host
|
179
|
+
run("#{ utility(:ssh) } #{ ssh_transport_args } #{ host } " +
|
180
|
+
%Q["mkdir -p '#{ remote_path }'"]) if mode == :ssh
|
181
|
+
else
|
182
|
+
FileUtils.mkdir_p(remote_path)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def host_options
|
187
|
+
@host_options ||= begin
|
188
|
+
if !host
|
189
|
+
''
|
190
|
+
elsif mode == :ssh
|
191
|
+
"#{ host }:"
|
192
|
+
else
|
193
|
+
user = "#{ rsync_user }@" if rsync_user
|
194
|
+
"#{ user }#{ host }::"
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def rsync_command
|
200
|
+
@rsync_command ||= begin
|
201
|
+
cmd = utility(:rsync) << ' --archive' <<
|
202
|
+
" #{ Array(additional_rsync_options).join(' ') }".rstrip
|
203
|
+
cmd << compress_option << password_option << transport_options if host
|
204
|
+
cmd
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def compress_option
|
209
|
+
compress ? ' --compress' : ''
|
210
|
+
end
|
211
|
+
|
212
|
+
def password_option
|
213
|
+
return '' if mode == :ssh
|
214
|
+
|
215
|
+
path = @password_file ? @password_file.path : rsync_password_file
|
216
|
+
path ? " --password-file='#{ File.expand_path(path) }'" : ''
|
217
|
+
end
|
218
|
+
|
219
|
+
def transport_options
|
220
|
+
if mode == :rsync_daemon
|
221
|
+
" --port #{ port }"
|
222
|
+
else
|
223
|
+
%Q[ -e "#{ utility(:ssh) } #{ ssh_transport_args }"]
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def ssh_transport_args
|
228
|
+
args = "-p #{ port } "
|
229
|
+
args << "-l #{ ssh_user } " if ssh_user
|
230
|
+
args << Array(additional_ssh_options).join(' ')
|
231
|
+
args.rstrip
|
232
|
+
end
|
233
|
+
|
234
|
+
def write_password_file
|
235
|
+
return unless host && rsync_password && mode != :ssh
|
236
|
+
|
237
|
+
@password_file = Tempfile.new('backup-rsync-password')
|
238
|
+
@password_file.write(rsync_password)
|
239
|
+
@password_file.close
|
240
|
+
end
|
241
|
+
|
242
|
+
def remove_password_file
|
243
|
+
@password_file.delete if @password_file
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|