backup 3.1.3 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Backup
4
- module Logger
4
+ class Logger
5
5
  class Console
6
6
  class Options
7
7
  ##
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Backup
4
- module Logger
4
+ class Logger
5
5
  class Logfile
6
6
  class Options
7
7
  ##
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Backup
4
- module Logger
4
+ class Logger
5
5
  class Syslog
6
6
  class Options
7
7
  ##
@@ -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(1) unless err.is_a?(StandardError)
244
+ exit(3) unless err.is_a?(StandardError)
245
245
  end
246
246
 
247
247
  private
@@ -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
- # `:smtp` [::Mail::SMTP] (default)
16
- # : Settings used only by this method:
17
- # : `address`, `port`, `domain`, `user_name`, `password`
18
- # : `authentication`, `enable_starttls_auto`, `openssl_verify_mode`
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
- # `:sendmail` [::Mail::Sendmail]
21
- # : Settings used only by this method:
22
- # : `sendmail`, `sendmail_args`
21
+ # [:sendmail - ::Mail::Sendmail]
22
+ # Settings used by this method:
23
+ # {#sendmail}, {#sendmail_args}
23
24
  #
24
- # `:exim` [::Mail::Exim]
25
- # : Settings used only by this method:
26
- # : `exim`, `exim_args`
25
+ # [:exim - ::Mail::Exim]
26
+ # Settings used by this method:
27
+ # {#exim}, {#exim_args}
27
28
  #
28
- # `:file` [::Mail::FileDelivery]
29
- # : Settings used only by this method:
30
- # : `mail_folder`
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 and Receiver email addresses
36
- # Examples:
37
- # sender - my.email.address@gmail.com
38
- # receiver - your.email.address@gmail.com
39
- attr_accessor :from, :to
36
+ # Sender Email Address
37
+ attr_accessor :from
38
+
39
+ ##
40
+ # Receiver Email Address
41
+ attr_accessor :to
40
42
 
41
43
  ##
42
- # The address to use
43
- # Example: smtp.gmail.com
44
+ # SMTP Server Address
44
45
  attr_accessor :address
45
46
 
46
47
  ##
47
- # The port to connect to
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
- # Username and Password (sender email's credentials)
58
- # Examples:
59
- # user_name - meskyanichi
60
- # password - my_secret_password
61
- attr_accessor :user_name, :password
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
- # Example: plain
65
+ #
66
+ # Acceptable values: +:plain+, +:login+, +:cram_md5+
66
67
  attr_accessor :authentication
67
68
 
68
69
  ##
69
- # Automatically set TLS
70
- # Example: true
71
- attr_accessor :enable_starttls_auto
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
- # Example: none - Only use this option for a self-signed and/or wildcard certificate
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` (if needed)
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` (if needed)
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
- # `:success`
123
- # : The backup completed successfully.
124
- # : Notification will be sent if `on_success` was set to `true`
153
+ # [:success]
154
+ # The backup completed successfully.
155
+ # Notification will be sent if `on_success` was set to `true`
125
156
  #
126
- # `:warning`
127
- # : The backup completed successfully, but warnings were logged
128
- # : Notification will be sent, including a copy of the current
129
- # : backup log, if `on_warning` was set to `true`
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
- # `:failure`
132
- # : The backup operation failed.
133
- # : Notification will be sent, including the Exception which caused
134
- # : the failure, the Exception's backtrace, a copy of the current
135
- # : backup log and other information if `on_failure` was set to `true`
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 => @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
@@ -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. This will be appended to the YAML storage file used for
17
- # cycling backups.
18
- attr_accessor :storage_id
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.backup.tar.enc"
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. "backup.tar.enc"
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]
@@ -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
- # Server credentials
14
- attr_accessor :username, :password
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 IP Address and SSH port
18
- attr_accessor :ip, :port
27
+ # Server Address
28
+ #
29
+ # If not specified, the storage operation will be local.
30
+ attr_accessor :host
19
31
 
20
32
  ##
21
- # Path to store backups to
22
- attr_accessor :path
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
- # Flag to use local backups
26
- attr_accessor :local
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
- # Creates a new instance of the storage object
30
- def initialize(model, storage_id = nil, &block)
31
- super(model, storage_id)
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
- @port ||= 22
34
- @path ||= 'backups'
35
- @local ||= false
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
- instance_eval(&block) if block_given?
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
- @path = path.sub(/^\~\//, '')
40
- end
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
- private
102
+ ##
103
+ # Additional String or Array of options for the rsync cli
104
+ attr_accessor :additional_rsync_options
43
105
 
44
106
  ##
45
- # This is the remote path to where the backup files will be stored
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
- # Establishes a connection to the remote server
54
- def connection
55
- Net::SSH.start(
56
- ip, username, :password => password, :port => port
57
- ) {|ssh| yield ssh }
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
- remote_path = remote_path_for(@package)
147
+ def transfer!
148
+ Logger.info "#{ storage_name } Started..."
66
149
 
67
- create_remote_path!(remote_path)
150
+ write_password_file!
151
+ create_dest_path!
68
152
 
69
153
  files_to_transfer_for(@package) do |local_file, remote_file|
70
- if local
71
- Logger.info "#{storage_name} started transferring " +
72
- "'#{ local_file }' to '#{ remote_path }'."
73
- run(
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! unless local
162
+ remove_password_file!
90
163
  end
91
164
 
92
165
  ##
93
- # Note: Storage::RSync doesn't cycle
94
- def remove!; end
166
+ # Storage::RSync doesn't cycle
167
+ def cycle!; end
95
168
 
96
169
  ##
97
- # Creates (if they don't exist yet) all the directories on the remote
98
- # server in order to upload the backup file.
99
- def create_remote_path!(remote_path)
100
- if @local
101
- FileUtils.mkdir_p(remote_path)
102
- else
103
- connection do |ssh|
104
- ssh.exec!("mkdir -p '#{ remote_path }'")
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
- # Writes the provided password to a temporary file so that
111
- # the rsync utility can read the password from this file
112
- def write_password_file!
113
- unless password.nil?
114
- @password_file = Tempfile.new('backup-rsync-password')
115
- @password_file.write(password)
116
- @password_file.close
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
- # Removes the previously created @password_file
122
- # (temporary file containing the password)
123
- def remove_password_file!
124
- @password_file.delete if @password_file
125
- @password_file = nil
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
- # Returns Rsync syntax for using a password file
130
- def rsync_password_file
131
- "--password-file='#{@password_file.path}'" if @password_file
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
- # Returns Rsync syntax for defining a port to connect to
136
- def rsync_port
137
- "-e 'ssh -p #{port}'"
231
+ def compress_option
232
+ compress ? ' --compress' : ''
138
233
  end
139
234
 
140
- ##
141
- # RSync options
142
- # -z = Compresses the bytes that will be transferred to reduce bandwidth usage
143
- def rsync_options
144
- "-z"
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