backup 3.1.3 → 3.2.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 +6 -14
- data/lib/backup.rb +1 -0
- data/lib/backup/archive.rb +106 -79
- data/lib/backup/cli.rb +23 -4
- data/lib/backup/logger.rb +103 -59
- data/lib/backup/logger/console.rb +1 -1
- data/lib/backup/logger/logfile.rb +1 -1
- data/lib/backup/logger/syslog.rb +1 -1
- data/lib/backup/model.rb +3 -3
- data/lib/backup/notifier/mail.rb +84 -50
- data/lib/backup/storage/base.rb +10 -14
- data/lib/backup/storage/rsync.rb +232 -92
- data/lib/backup/syncer/base.rb +23 -8
- data/lib/backup/syncer/cloud/base.rb +4 -3
- data/lib/backup/syncer/cloud/cloud_files.rb +1 -1
- data/lib/backup/syncer/cloud/s3.rb +1 -1
- data/lib/backup/syncer/rsync/base.rb +13 -25
- data/lib/backup/syncer/rsync/local.rb +16 -30
- data/lib/backup/syncer/rsync/pull.rb +47 -11
- data/lib/backup/syncer/rsync/push.rb +167 -56
- data/lib/backup/utilities.rb +115 -104
- data/lib/backup/version.rb +1 -1
- data/templates/cli/archive +15 -7
- data/templates/cli/notifier/mail +1 -1
- data/templates/cli/storage/rsync +15 -7
- data/templates/cli/syncer/rsync_local +1 -1
- data/templates/cli/syncer/rsync_pull +10 -5
- data/templates/cli/syncer/rsync_push +10 -5
- metadata +7 -6
data/lib/backup/logger/syslog.rb
CHANGED
data/lib/backup/model.rb
CHANGED
@@ -112,7 +112,7 @@ module Backup
|
|
112
112
|
##
|
113
113
|
# Adds a syncer method to the array of syncer
|
114
114
|
# methods to use during the backup process
|
115
|
-
def sync_with(name, &block)
|
115
|
+
def sync_with(name, syncer_id = nil, &block)
|
116
116
|
##
|
117
117
|
# Warn user of DSL changes
|
118
118
|
case name.to_s
|
@@ -134,7 +134,7 @@ module Backup
|
|
134
134
|
EOS
|
135
135
|
name = "Cloud::#{ syncer }"
|
136
136
|
end
|
137
|
-
@syncers << get_class_from_scope(Syncer, name).new(&block)
|
137
|
+
@syncers << get_class_from_scope(Syncer, name).new(syncer_id, &block)
|
138
138
|
end
|
139
139
|
|
140
140
|
##
|
@@ -241,7 +241,7 @@ module Backup
|
|
241
241
|
rescue Exception => err
|
242
242
|
log!(:failure, err)
|
243
243
|
send_failure_notifications
|
244
|
-
exit(
|
244
|
+
exit(3) unless err.is_a?(StandardError)
|
245
245
|
end
|
246
246
|
|
247
247
|
private
|
data/lib/backup/notifier/mail.rb
CHANGED
@@ -10,101 +10,131 @@ module Backup
|
|
10
10
|
|
11
11
|
##
|
12
12
|
# Mail delivery method to be used by the Mail gem.
|
13
|
+
#
|
13
14
|
# Supported methods:
|
14
15
|
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
16
|
+
# [:smtp - ::Mail::SMTP (default)]
|
17
|
+
# Settings used by this method:
|
18
|
+
# {#address}, {#port}, {#domain}, {#user_name}, {#password},
|
19
|
+
# {#authentication}, {#encryption}, {#openssl_verify_mode}
|
19
20
|
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
21
|
+
# [:sendmail - ::Mail::Sendmail]
|
22
|
+
# Settings used by this method:
|
23
|
+
# {#sendmail}, {#sendmail_args}
|
23
24
|
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
25
|
+
# [:exim - ::Mail::Exim]
|
26
|
+
# Settings used by this method:
|
27
|
+
# {#exim}, {#exim_args}
|
27
28
|
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
29
|
+
# [:file - ::Mail::FileDelivery]
|
30
|
+
# Settings used by this method:
|
31
|
+
# {#mail_folder}
|
31
32
|
#
|
32
33
|
attr_accessor :delivery_method
|
33
34
|
|
34
35
|
##
|
35
|
-
# Sender
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
# Sender Email Address
|
37
|
+
attr_accessor :from
|
38
|
+
|
39
|
+
##
|
40
|
+
# Receiver Email Address
|
41
|
+
attr_accessor :to
|
40
42
|
|
41
43
|
##
|
42
|
-
#
|
43
|
-
# Example: smtp.gmail.com
|
44
|
+
# SMTP Server Address
|
44
45
|
attr_accessor :address
|
45
46
|
|
46
47
|
##
|
47
|
-
#
|
48
|
-
# Example: 587
|
48
|
+
# SMTP Server Port
|
49
49
|
attr_accessor :port
|
50
50
|
|
51
51
|
##
|
52
52
|
# Your domain (if applicable)
|
53
|
-
# Example: mydomain.com
|
54
53
|
attr_accessor :domain
|
55
54
|
|
56
55
|
##
|
57
|
-
#
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
56
|
+
# SMTP Server Username (sender email's credentials)
|
57
|
+
attr_accessor :user_name
|
58
|
+
|
59
|
+
##
|
60
|
+
# SMTP Server Password (sender email's credentials)
|
61
|
+
attr_accessor :password
|
62
62
|
|
63
63
|
##
|
64
64
|
# Authentication type
|
65
|
-
#
|
65
|
+
#
|
66
|
+
# Acceptable values: +:plain+, +:login+, +:cram_md5+
|
66
67
|
attr_accessor :authentication
|
67
68
|
|
68
69
|
##
|
69
|
-
#
|
70
|
-
#
|
71
|
-
|
70
|
+
# Set the method of encryption to be used for the +SMTP+ connection.
|
71
|
+
#
|
72
|
+
# [:none (default)]
|
73
|
+
# No encryption will be used.
|
74
|
+
#
|
75
|
+
# [:starttls]
|
76
|
+
# Use +STARTTLS+ to upgrade the connection to a +SSL/TLS+ connection.
|
77
|
+
#
|
78
|
+
# [:tls or :ssl]
|
79
|
+
# Use a +SSL/TLS+ connection.
|
80
|
+
attr_accessor :encryption
|
81
|
+
|
82
|
+
attr_deprecate :enable_starttls_auto, :version => '3.2.0',
|
83
|
+
:message => "Use #encryption instead.\n" +
|
84
|
+
'e.g. mail.encryption = :starttls',
|
85
|
+
:action => lambda {|klass, val|
|
86
|
+
klass.encryption = val ? :starttls : :none
|
87
|
+
}
|
72
88
|
|
73
89
|
##
|
74
90
|
# OpenSSL Verify Mode
|
75
|
-
#
|
91
|
+
#
|
92
|
+
# Valid modes: +:none+, +:peer+, +:client_once+, +:fail_if_no_peer_cert+
|
93
|
+
# See +OpenSSL::SSL+ for details.
|
94
|
+
#
|
95
|
+
# Use +:none+ for a self-signed and/or wildcard certificate
|
76
96
|
attr_accessor :openssl_verify_mode
|
77
97
|
|
78
98
|
##
|
99
|
+
# Path to `sendmail` (if needed)
|
100
|
+
#
|
79
101
|
# When using the `:sendmail` `delivery_method` option,
|
80
|
-
# this may be used to specify the absolute path to `sendmail`
|
102
|
+
# this may be used to specify the absolute path to `sendmail`
|
103
|
+
#
|
81
104
|
# Example: '/usr/sbin/sendmail'
|
82
105
|
attr_accessor :sendmail
|
83
106
|
|
84
107
|
##
|
85
108
|
# Optional arguments to pass to `sendmail`
|
109
|
+
#
|
86
110
|
# Note that this will override the defaults set by the Mail gem (currently: '-i -t')
|
87
111
|
# So, if set here, be sure to set all the arguments you require.
|
112
|
+
#
|
88
113
|
# Example: '-i -t -X/tmp/traffic.log'
|
89
114
|
attr_accessor :sendmail_args
|
90
115
|
|
91
116
|
##
|
117
|
+
# Path to `exim` (if needed)
|
118
|
+
#
|
92
119
|
# When using the `:exim` `delivery_method` option,
|
93
|
-
# this may be used to specify the absolute path to `exim`
|
120
|
+
# this may be used to specify the absolute path to `exim`
|
121
|
+
#
|
94
122
|
# Example: '/usr/sbin/exim'
|
95
123
|
attr_accessor :exim
|
96
124
|
|
97
125
|
##
|
98
126
|
# Optional arguments to pass to `exim`
|
127
|
+
#
|
99
128
|
# Note that this will override the defaults set by the Mail gem (currently: '-i -t')
|
100
129
|
# So, if set here, be sure to set all the arguments you require.
|
130
|
+
#
|
101
131
|
# Example: '-i -t -X/tmp/traffic.log'
|
102
132
|
attr_accessor :exim_args
|
103
133
|
|
104
134
|
##
|
105
135
|
# Folder where mail will be kept when using the `:file` `delivery_method` option.
|
136
|
+
#
|
106
137
|
# Default location is '$HOME/Backup/emails'
|
107
|
-
# Example: '/tmp/test-mails'
|
108
138
|
attr_accessor :mail_folder
|
109
139
|
|
110
140
|
def initialize(model, &block)
|
@@ -117,22 +147,23 @@ module Backup
|
|
117
147
|
|
118
148
|
##
|
119
149
|
# Notify the user of the backup operation results.
|
150
|
+
#
|
120
151
|
# `status` indicates one of the following:
|
121
152
|
#
|
122
|
-
#
|
123
|
-
#
|
124
|
-
#
|
153
|
+
# [:success]
|
154
|
+
# The backup completed successfully.
|
155
|
+
# Notification will be sent if `on_success` was set to `true`
|
125
156
|
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
#
|
157
|
+
# [:warning]
|
158
|
+
# The backup completed successfully, but warnings were logged
|
159
|
+
# Notification will be sent, including a copy of the current
|
160
|
+
# backup log, if `on_warning` was set to `true`
|
130
161
|
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
#
|
134
|
-
#
|
135
|
-
#
|
162
|
+
# [:failure]
|
163
|
+
# The backup operation failed.
|
164
|
+
# Notification will be sent, including the Exception which caused
|
165
|
+
# the failure, the Exception's backtrace, a copy of the current
|
166
|
+
# backup log and other information if `on_failure` was set to `true`
|
136
167
|
#
|
137
168
|
def notify!(status)
|
138
169
|
name, send_log =
|
@@ -173,8 +204,11 @@ module Backup
|
|
173
204
|
:user_name => @user_name,
|
174
205
|
:password => @password,
|
175
206
|
:authentication => @authentication,
|
176
|
-
:enable_starttls_auto => @
|
177
|
-
:openssl_verify_mode => @openssl_verify_mode
|
207
|
+
:enable_starttls_auto => @encryption == :starttls,
|
208
|
+
:openssl_verify_mode => @openssl_verify_mode,
|
209
|
+
:ssl => @encryption == :ssl,
|
210
|
+
:tls => @encryption == :tls
|
211
|
+
}
|
178
212
|
when 'sendmail'
|
179
213
|
opts = {}
|
180
214
|
opts.merge!(:location => File.expand_path(@sendmail)) if @sendmail
|
data/lib/backup/storage/base.rb
CHANGED
@@ -11,23 +11,19 @@ module Backup
|
|
11
11
|
attr_accessor :keep
|
12
12
|
|
13
13
|
##
|
14
|
-
# (Optional)
|
15
14
|
# User-defined string used to uniquely identify multiple storages of the
|
16
|
-
# same type.
|
17
|
-
#
|
18
|
-
|
15
|
+
# same type. If multiple storages of the same type are added to a single
|
16
|
+
# backup model, then this identifier must be set. This will be appended
|
17
|
+
# to the YAML storage file used for cycling backups.
|
18
|
+
attr_reader :storage_id
|
19
19
|
|
20
|
-
##
|
21
|
-
# Creates a new instance of the storage object
|
22
|
-
# * Called with super(model, storage_id) from each subclass
|
23
20
|
def initialize(model, storage_id = nil)
|
24
|
-
load_defaults!
|
25
21
|
@model = model
|
26
22
|
@storage_id = storage_id
|
23
|
+
|
24
|
+
load_defaults!
|
27
25
|
end
|
28
26
|
|
29
|
-
##
|
30
|
-
# Performs the backup transfer
|
31
27
|
def perform!
|
32
28
|
@package = @model.package
|
33
29
|
transfer!
|
@@ -50,8 +46,8 @@ module Backup
|
|
50
46
|
##
|
51
47
|
# Return the storage name, with optional storage_id
|
52
48
|
def storage_name
|
53
|
-
self.class.to_s.sub('Backup::', '') +
|
54
|
-
(storage_id ? " (#{storage_id})" : '')
|
49
|
+
@storage_name ||= self.class.to_s.sub('Backup::', '') +
|
50
|
+
(storage_id ? " (#{ storage_id })" : '')
|
55
51
|
end
|
56
52
|
|
57
53
|
##
|
@@ -71,9 +67,9 @@ module Backup
|
|
71
67
|
##
|
72
68
|
# Yields two arguments to the given block: "local_file, remote_file"
|
73
69
|
# The local_file is the full file name:
|
74
|
-
# e.g. "2011.08.30.11.00.02.
|
70
|
+
# e.g. "2011.08.30.11.00.02.trigger.tar.enc"
|
75
71
|
# The remote_file is the full file name, minus the timestamp:
|
76
|
-
# e.g. "
|
72
|
+
# e.g. "trigger.tar.enc"
|
77
73
|
def files_to_transfer_for(package)
|
78
74
|
package.filenames.each do |filename|
|
79
75
|
yield filename, filename[20..-1]
|
data/lib/backup/storage/rsync.rb
CHANGED
@@ -1,149 +1,289 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
##
|
4
|
-
# Only load the Net::SSH library when the Backup::Storage::RSync class is loaded
|
5
|
-
Backup::Dependency.load('net-ssh')
|
6
|
-
|
7
3
|
module Backup
|
8
4
|
module Storage
|
9
5
|
class RSync < Base
|
10
6
|
include Backup::Utilities::Helpers
|
11
7
|
|
12
8
|
##
|
13
|
-
#
|
14
|
-
|
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
|
15
25
|
|
16
26
|
##
|
17
|
-
# Server
|
18
|
-
|
27
|
+
# Server Address
|
28
|
+
#
|
29
|
+
# If not specified, the storage operation will be local.
|
30
|
+
attr_accessor :host
|
19
31
|
|
20
32
|
##
|
21
|
-
#
|
22
|
-
|
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
|
23
41
|
|
24
42
|
##
|
25
|
-
#
|
26
|
-
|
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
|
27
56
|
|
28
57
|
##
|
29
|
-
#
|
30
|
-
|
31
|
-
|
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
|
32
72
|
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
36
81
|
|
37
|
-
|
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
|
38
92
|
|
39
|
-
|
40
|
-
|
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
|
41
101
|
|
42
|
-
|
102
|
+
##
|
103
|
+
# Additional String or Array of options for the rsync cli
|
104
|
+
attr_accessor :additional_rsync_options
|
43
105
|
|
44
106
|
##
|
45
|
-
#
|
46
|
-
|
47
|
-
# Note: This overrides the superclass' method
|
48
|
-
def remote_path_for(package)
|
49
|
-
File.join(path, package.trigger)
|
50
|
-
end
|
107
|
+
# Flag for compressing (only compresses for the transfer)
|
108
|
+
attr_accessor :compress
|
51
109
|
|
52
110
|
##
|
53
|
-
#
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
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, the files will be stored
|
124
|
+
# directly to the +path+ given. The path (or path defined by your rsync
|
125
|
+
# module) must already exist.
|
126
|
+
# Note that no additional `<trigger>` directory will be added to this path.
|
127
|
+
#
|
128
|
+
# In :ssh mode or local operation (no +host+ specified), the actual
|
129
|
+
# destination path will be `<path>/<trigger>/`. This path will be created
|
130
|
+
# if needed - either locally, or on the remote for :ssh mode.
|
131
|
+
# This behavior will change in v4.0, when :ssh mode and local operations
|
132
|
+
# will also store the files directly in the +path+ given.
|
133
|
+
attr_accessor :path
|
134
|
+
|
135
|
+
def initialize(model, storage_id = nil, &block)
|
136
|
+
super
|
137
|
+
instance_eval(&block) if block_given?
|
138
|
+
|
139
|
+
@mode ||= :ssh
|
140
|
+
@port ||= mode == :rsync_daemon ? 873 : 22
|
141
|
+
@compress ||= false
|
142
|
+
@path ||= '~/backups'
|
58
143
|
end
|
59
144
|
|
60
|
-
|
61
|
-
# Transfers the archived file to the specified remote server
|
62
|
-
def transfer!
|
63
|
-
write_password_file! unless local
|
145
|
+
private
|
64
146
|
|
65
|
-
|
147
|
+
def transfer!
|
148
|
+
Logger.info "#{ storage_name } Started..."
|
66
149
|
|
67
|
-
|
150
|
+
write_password_file!
|
151
|
+
create_dest_path!
|
68
152
|
|
69
153
|
files_to_transfer_for(@package) do |local_file, remote_file|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
"#{ utility(:rsync) } '#{ File.join(local_path, local_file) }' " +
|
75
|
-
"'#{ File.join(remote_path, remote_file) }'"
|
76
|
-
)
|
77
|
-
else
|
78
|
-
Logger.info "#{storage_name} started transferring " +
|
79
|
-
"'#{ local_file }' to '#{ ip }'."
|
80
|
-
run(
|
81
|
-
"#{ utility(:rsync) } #{ rsync_options } #{ rsync_port } " +
|
82
|
-
"#{ rsync_password_file } '#{ File.join(local_path, local_file) }' " +
|
83
|
-
"'#{ username }@#{ ip }:#{ File.join(remote_path, remote_file) }'"
|
84
|
-
)
|
85
|
-
end
|
154
|
+
src = "'#{ File.join(local_path, local_file) }'"
|
155
|
+
dest = "#{ host_options }'#{ File.join(dest_path, remote_file) }'"
|
156
|
+
Logger.info "Syncing to #{ dest }..."
|
157
|
+
run("#{ rsync_command } #{ src } #{ dest }")
|
86
158
|
end
|
87
159
|
|
160
|
+
Logger.info "#{ storage_name } Finished!"
|
88
161
|
ensure
|
89
|
-
remove_password_file!
|
162
|
+
remove_password_file!
|
90
163
|
end
|
91
164
|
|
92
165
|
##
|
93
|
-
#
|
94
|
-
def
|
166
|
+
# Storage::RSync doesn't cycle
|
167
|
+
def cycle!; end
|
95
168
|
|
96
169
|
##
|
97
|
-
#
|
98
|
-
#
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
170
|
+
# Other storages use #remote_path_for to set the dest_path,
|
171
|
+
# which adds an additional timestamp directory to the path.
|
172
|
+
# This is not desired here, since we need to transfer the package files
|
173
|
+
# to the same location each time.
|
174
|
+
#
|
175
|
+
# Note: In v4.0, the additional trigger directory will to be dropped
|
176
|
+
# from dest_path for both local and :ssh mode, so the package files will
|
177
|
+
# be stored directly in #path.
|
178
|
+
def dest_path
|
179
|
+
@dest_path ||= begin
|
180
|
+
if host
|
181
|
+
if mode == :ssh
|
182
|
+
File.join(path.sub(/^~\//, ''), @package.trigger)
|
183
|
+
else
|
184
|
+
path.sub(/^~\//, '').sub(/\/$/, '')
|
185
|
+
end
|
186
|
+
else
|
187
|
+
File.join(File.expand_path(path), @package.trigger)
|
105
188
|
end
|
106
189
|
end
|
107
190
|
end
|
108
191
|
|
109
192
|
##
|
110
|
-
#
|
111
|
-
#
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
193
|
+
# Runs a 'mkdir -p' command on the host (or locally) to ensure the
|
194
|
+
# dest_path exists. This is used because we're transferring a single
|
195
|
+
# file, and rsync won't attempt to create the intermediate directories.
|
196
|
+
#
|
197
|
+
# This is only applicable locally and in :ssh mode.
|
198
|
+
# In :ssh_daemon and :rsync_daemon modes the `path` would include a
|
199
|
+
# module name that must define a path on the remote that already exists.
|
200
|
+
def create_dest_path!
|
201
|
+
if host
|
202
|
+
run("#{ utility(:ssh) } #{ ssh_transport_args } #{ host } " +
|
203
|
+
%Q["mkdir -p '#{ dest_path }'"]) if mode == :ssh
|
204
|
+
else
|
205
|
+
FileUtils.mkdir_p dest_path
|
117
206
|
end
|
118
207
|
end
|
119
208
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
209
|
+
def host_options
|
210
|
+
@host_options ||= begin
|
211
|
+
if !host
|
212
|
+
''
|
213
|
+
elsif mode == :ssh
|
214
|
+
"#{ host }:"
|
215
|
+
else
|
216
|
+
user = "#{ rsync_user }@" if rsync_user
|
217
|
+
"#{ user }#{ host }::"
|
218
|
+
end
|
219
|
+
end
|
126
220
|
end
|
127
221
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
222
|
+
def rsync_command
|
223
|
+
@rsync_command ||= begin
|
224
|
+
cmd = utility(:rsync) << ' --archive' <<
|
225
|
+
" #{ Array(additional_rsync_options).join(' ') }".rstrip
|
226
|
+
cmd << compress_option << password_option << transport_options if host
|
227
|
+
cmd
|
228
|
+
end
|
132
229
|
end
|
133
230
|
|
134
|
-
|
135
|
-
|
136
|
-
def rsync_port
|
137
|
-
"-e 'ssh -p #{port}'"
|
231
|
+
def compress_option
|
232
|
+
compress ? ' --compress' : ''
|
138
233
|
end
|
139
234
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
"-
|
235
|
+
def password_option
|
236
|
+
return '' if mode == :ssh
|
237
|
+
|
238
|
+
path = @password_file ? @password_file.path : rsync_password_file
|
239
|
+
path ? " --password-file='#{ File.expand_path(path) }'" : ''
|
240
|
+
end
|
241
|
+
|
242
|
+
def transport_options
|
243
|
+
if mode == :rsync_daemon
|
244
|
+
" --port #{ port }"
|
245
|
+
else
|
246
|
+
%Q[ -e "#{ utility(:ssh) } #{ ssh_transport_args }"]
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def ssh_transport_args
|
251
|
+
args = "-p #{ port } "
|
252
|
+
args << "-l #{ ssh_user } " if ssh_user
|
253
|
+
args << Array(additional_ssh_options).join(' ')
|
254
|
+
args.rstrip
|
255
|
+
end
|
256
|
+
|
257
|
+
def write_password_file!
|
258
|
+
return unless host && rsync_password && mode != :ssh
|
259
|
+
|
260
|
+
@password_file = Tempfile.new('backup-rsync-password')
|
261
|
+
@password_file.write(rsync_password)
|
262
|
+
@password_file.close
|
145
263
|
end
|
146
264
|
|
265
|
+
def remove_password_file!
|
266
|
+
@password_file.delete if @password_file
|
267
|
+
end
|
268
|
+
|
269
|
+
attr_deprecate :local, :version => '3.2.0',
|
270
|
+
:message => "If 'host' is not set, the operation will be local."
|
271
|
+
|
272
|
+
attr_deprecate :username, :version => '3.2.0',
|
273
|
+
:message => 'Use #ssh_user instead.',
|
274
|
+
:action => lambda {|klass, val|
|
275
|
+
klass.ssh_user = val
|
276
|
+
}
|
277
|
+
attr_deprecate :password, :version => '3.2.0',
|
278
|
+
:message => 'Use #rsync_password instead.',
|
279
|
+
:action => lambda {|klass, val|
|
280
|
+
klass.rsync_password = val
|
281
|
+
}
|
282
|
+
attr_deprecate :ip, :version => '3.2.0',
|
283
|
+
:message => 'Use #host instead.',
|
284
|
+
:action => lambda {|klass, val|
|
285
|
+
klass.host = val
|
286
|
+
}
|
147
287
|
end
|
148
288
|
end
|
149
289
|
end
|