interu-backup 3.0.16

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.
Files changed (151) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +31 -0
  3. data/Gemfile.lock +117 -0
  4. data/Guardfile +17 -0
  5. data/LICENSE.md +24 -0
  6. data/README.md +332 -0
  7. data/backup.gemspec +31 -0
  8. data/bin/backup +267 -0
  9. data/lib/backup.rb +181 -0
  10. data/lib/backup/archive.rb +73 -0
  11. data/lib/backup/cli.rb +82 -0
  12. data/lib/backup/compressor/base.rb +17 -0
  13. data/lib/backup/compressor/bzip2.rb +64 -0
  14. data/lib/backup/compressor/gzip.rb +61 -0
  15. data/lib/backup/configuration/base.rb +15 -0
  16. data/lib/backup/configuration/compressor/base.rb +10 -0
  17. data/lib/backup/configuration/compressor/bzip2.rb +23 -0
  18. data/lib/backup/configuration/compressor/gzip.rb +23 -0
  19. data/lib/backup/configuration/database/base.rb +18 -0
  20. data/lib/backup/configuration/database/mongodb.rb +41 -0
  21. data/lib/backup/configuration/database/mysql.rb +37 -0
  22. data/lib/backup/configuration/database/postgresql.rb +37 -0
  23. data/lib/backup/configuration/database/redis.rb +35 -0
  24. data/lib/backup/configuration/encryptor/base.rb +10 -0
  25. data/lib/backup/configuration/encryptor/gpg.rb +17 -0
  26. data/lib/backup/configuration/encryptor/open_ssl.rb +26 -0
  27. data/lib/backup/configuration/helpers.rb +54 -0
  28. data/lib/backup/configuration/notifier/base.rb +39 -0
  29. data/lib/backup/configuration/notifier/campfire.rb +25 -0
  30. data/lib/backup/configuration/notifier/mail.rb +52 -0
  31. data/lib/backup/configuration/notifier/presently.rb +25 -0
  32. data/lib/backup/configuration/notifier/twitter.rb +21 -0
  33. data/lib/backup/configuration/storage/base.rb +18 -0
  34. data/lib/backup/configuration/storage/cloudfiles.rb +21 -0
  35. data/lib/backup/configuration/storage/dropbox.rb +29 -0
  36. data/lib/backup/configuration/storage/ftp.rb +25 -0
  37. data/lib/backup/configuration/storage/rsync.rb +25 -0
  38. data/lib/backup/configuration/storage/s3.rb +25 -0
  39. data/lib/backup/configuration/storage/scp.rb +25 -0
  40. data/lib/backup/configuration/storage/sftp.rb +25 -0
  41. data/lib/backup/configuration/syncer/rsync.rb +45 -0
  42. data/lib/backup/configuration/syncer/s3.rb +33 -0
  43. data/lib/backup/database/base.rb +33 -0
  44. data/lib/backup/database/mongodb.rb +179 -0
  45. data/lib/backup/database/mysql.rb +104 -0
  46. data/lib/backup/database/postgresql.rb +111 -0
  47. data/lib/backup/database/redis.rb +105 -0
  48. data/lib/backup/dependency.rb +96 -0
  49. data/lib/backup/encryptor/base.rb +17 -0
  50. data/lib/backup/encryptor/gpg.rb +78 -0
  51. data/lib/backup/encryptor/open_ssl.rb +67 -0
  52. data/lib/backup/exception/command_not_found.rb +8 -0
  53. data/lib/backup/finder.rb +39 -0
  54. data/lib/backup/logger.rb +102 -0
  55. data/lib/backup/model.rb +272 -0
  56. data/lib/backup/notifier/base.rb +29 -0
  57. data/lib/backup/notifier/binder.rb +32 -0
  58. data/lib/backup/notifier/campfire.rb +194 -0
  59. data/lib/backup/notifier/mail.rb +141 -0
  60. data/lib/backup/notifier/presently.rb +105 -0
  61. data/lib/backup/notifier/templates/notify_failure.erb +33 -0
  62. data/lib/backup/notifier/templates/notify_success.erb +16 -0
  63. data/lib/backup/notifier/twitter.rb +87 -0
  64. data/lib/backup/storage/base.rb +67 -0
  65. data/lib/backup/storage/cloudfiles.rb +95 -0
  66. data/lib/backup/storage/dropbox.rb +91 -0
  67. data/lib/backup/storage/ftp.rb +114 -0
  68. data/lib/backup/storage/object.rb +45 -0
  69. data/lib/backup/storage/rsync.rb +129 -0
  70. data/lib/backup/storage/s3.rb +180 -0
  71. data/lib/backup/storage/scp.rb +106 -0
  72. data/lib/backup/storage/sftp.rb +106 -0
  73. data/lib/backup/syncer/base.rb +10 -0
  74. data/lib/backup/syncer/rsync.rb +152 -0
  75. data/lib/backup/syncer/s3.rb +118 -0
  76. data/lib/backup/version.rb +43 -0
  77. data/lib/templates/archive +7 -0
  78. data/lib/templates/compressor/bzip2 +7 -0
  79. data/lib/templates/compressor/gzip +7 -0
  80. data/lib/templates/database/mongodb +14 -0
  81. data/lib/templates/database/mysql +14 -0
  82. data/lib/templates/database/postgresql +14 -0
  83. data/lib/templates/database/redis +13 -0
  84. data/lib/templates/encryptor/gpg +12 -0
  85. data/lib/templates/encryptor/openssl +8 -0
  86. data/lib/templates/notifier/campfire +11 -0
  87. data/lib/templates/notifier/mail +17 -0
  88. data/lib/templates/notifier/presently +12 -0
  89. data/lib/templates/notifier/twitter +12 -0
  90. data/lib/templates/readme +15 -0
  91. data/lib/templates/storage/cloudfiles +10 -0
  92. data/lib/templates/storage/dropbox +12 -0
  93. data/lib/templates/storage/ftp +11 -0
  94. data/lib/templates/storage/rsync +10 -0
  95. data/lib/templates/storage/s3 +21 -0
  96. data/lib/templates/storage/scp +11 -0
  97. data/lib/templates/storage/sftp +11 -0
  98. data/lib/templates/syncer/rsync +17 -0
  99. data/lib/templates/syncer/s3 +15 -0
  100. data/spec/archive_spec.rb +90 -0
  101. data/spec/backup_spec.rb +11 -0
  102. data/spec/compressor/bzip2_spec.rb +59 -0
  103. data/spec/compressor/gzip_spec.rb +59 -0
  104. data/spec/configuration/base_spec.rb +35 -0
  105. data/spec/configuration/compressor/gzip_spec.rb +28 -0
  106. data/spec/configuration/database/base_spec.rb +16 -0
  107. data/spec/configuration/database/mongodb_spec.rb +30 -0
  108. data/spec/configuration/database/mysql_spec.rb +32 -0
  109. data/spec/configuration/database/postgresql_spec.rb +32 -0
  110. data/spec/configuration/database/redis_spec.rb +30 -0
  111. data/spec/configuration/encryptor/gpg_spec.rb +25 -0
  112. data/spec/configuration/encryptor/open_ssl_spec.rb +31 -0
  113. data/spec/configuration/notifier/campfire_spec.rb +20 -0
  114. data/spec/configuration/notifier/mail_spec.rb +32 -0
  115. data/spec/configuration/notifier/twitter_spec.rb +22 -0
  116. data/spec/configuration/storage/cloudfiles_spec.rb +34 -0
  117. data/spec/configuration/storage/dropbox_spec.rb +43 -0
  118. data/spec/configuration/storage/ftp_spec.rb +40 -0
  119. data/spec/configuration/storage/rsync_spec.rb +37 -0
  120. data/spec/configuration/storage/s3_spec.rb +37 -0
  121. data/spec/configuration/storage/scp_spec.rb +40 -0
  122. data/spec/configuration/storage/sftp_spec.rb +40 -0
  123. data/spec/configuration/syncer/rsync_spec.rb +46 -0
  124. data/spec/configuration/syncer/s3_spec.rb +43 -0
  125. data/spec/database/base_spec.rb +30 -0
  126. data/spec/database/mongodb_spec.rb +181 -0
  127. data/spec/database/mysql_spec.rb +150 -0
  128. data/spec/database/postgresql_spec.rb +164 -0
  129. data/spec/database/redis_spec.rb +122 -0
  130. data/spec/encryptor/gpg_spec.rb +57 -0
  131. data/spec/encryptor/open_ssl_spec.rb +102 -0
  132. data/spec/logger_spec.rb +58 -0
  133. data/spec/model_spec.rb +236 -0
  134. data/spec/notifier/campfire_spec.rb +96 -0
  135. data/spec/notifier/mail_spec.rb +97 -0
  136. data/spec/notifier/presently_spec.rb +99 -0
  137. data/spec/notifier/twitter_spec.rb +86 -0
  138. data/spec/spec_helper.rb +25 -0
  139. data/spec/storage/base_spec.rb +33 -0
  140. data/spec/storage/cloudfiles_spec.rb +102 -0
  141. data/spec/storage/dropbox_spec.rb +105 -0
  142. data/spec/storage/ftp_spec.rb +133 -0
  143. data/spec/storage/object_spec.rb +74 -0
  144. data/spec/storage/rsync_spec.rb +131 -0
  145. data/spec/storage/s3_spec.rb +110 -0
  146. data/spec/storage/scp_spec.rb +129 -0
  147. data/spec/storage/sftp_spec.rb +125 -0
  148. data/spec/syncer/rsync_spec.rb +195 -0
  149. data/spec/syncer/s3_spec.rb +139 -0
  150. data/spec/version_spec.rb +21 -0
  151. metadata +231 -0
@@ -0,0 +1,33 @@
1
+
2
+ There seemed to be a problem backing up <%= @model.label %> (<%= @model.trigger %>).
3
+
4
+ ===========================================================================
5
+ Exception that got raised:
6
+ <%= @exception.class %> - <%= @exception.to_s %>
7
+ ===========================================================================
8
+ <%= @exception.backtrace.join("\n") %>
9
+ ===========================================================================
10
+
11
+
12
+ You are running Backup version:
13
+ <%= Backup::Version.current %>
14
+
15
+ You are running Ruby version:
16
+ <%= RUBY_VERSION %> (patchlevel <%= RUBY_PATCHLEVEL %>)
17
+
18
+ On platform:
19
+ <%= RUBY_PLATFORM %>
20
+
21
+ ---------------------------------------------------------------------------
22
+
23
+ View all Backup gem releases here:
24
+ http://rubygems.org/gems/backup
25
+
26
+ View the Backup git repository here:
27
+ https://github.com/meskyanichi/backup
28
+
29
+ View the Backup issues here:
30
+ https://github.com/meskyanichi/backup/issues
31
+
32
+ View the Backup wiki here:
33
+ https://github.com/meskyanichi/backup/wiki
@@ -0,0 +1,16 @@
1
+
2
+ Backup <%= @model.label %> (<%= @model.trigger %>) finished without any errors!
3
+
4
+ ---------------------------------------------------------------------------
5
+
6
+ View all Backup gem releases here:
7
+ http://rubygems.org/gems/backup
8
+
9
+ View the Backup git repository here:
10
+ https://github.com/meskyanichi/backup
11
+
12
+ View the Backup issues here:
13
+ https://github.com/meskyanichi/backup/issues
14
+
15
+ View the Backup wiki here:
16
+ https://github.com/meskyanichi/backup/wiki
@@ -0,0 +1,87 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Only load the Twitter gem when using Twitter notifications
5
+ Backup::Dependency.load('twitter')
6
+
7
+ module Backup
8
+ module Notifier
9
+ class Twitter < Base
10
+
11
+ ##
12
+ # Container for the Twitter Client object
13
+ attr_accessor :twitter_client
14
+
15
+ ##
16
+ # Container for the Model object
17
+ attr_accessor :model
18
+
19
+ ##
20
+ # Twitter consumer key credentials
21
+ attr_accessor :consumer_key, :consumer_secret
22
+
23
+ ##
24
+ # OAuth credentials
25
+ attr_accessor :oauth_token, :oauth_token_secret
26
+
27
+ ##
28
+ # Instantiates a new Backup::Notifier::Twitter object
29
+ def initialize(&block)
30
+ load_defaults!
31
+
32
+ instance_eval(&block) if block_given?
33
+
34
+ set_defaults!
35
+ end
36
+
37
+ ##
38
+ # Performs the notification
39
+ # Takes an exception object that might've been created if an exception occurred.
40
+ # If this is the case it'll invoke notify_failure!(exception), otherwise, if no
41
+ # error was raised, it'll go ahead and notify_success!
42
+ #
43
+ # If'll only perform these if on_success is true or on_failure is true
44
+ def perform!(model, exception = false)
45
+ @model = model
46
+
47
+ if notify_on_success? and exception.eql?(false)
48
+ log!
49
+ notify_success!
50
+ elsif notify_on_failure? and not exception.eql?(false)
51
+ log!
52
+ notify_failure!(exception)
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ ##
59
+ # Sends a tweet informing the user that the backup operation
60
+ # proceeded without any errors
61
+ def notify_success!
62
+ twitter_client.update("[Backup::Succeeded] #{model.label} (#{ File.basename(Backup::Model.file) })")
63
+ end
64
+
65
+ ##
66
+ # Sends a tweet informing the user that the backup operation
67
+ # raised an exception
68
+ def notify_failure!(exception)
69
+ twitter_client.update("[Backup::Failed] #{model.label} (#{ File.basename(Backup::Model.file) })")
70
+ end
71
+
72
+ ##
73
+ # Configures the Twitter object by passing in the @consumer_key, @consumer_secret
74
+ # @oauth_token and @oauth_token_secret. Instantiates and sets the @twitter_client object
75
+ def set_defaults!
76
+ ::Twitter.configure do |config|
77
+ config.consumer_key = @consumer_key
78
+ config.consumer_secret = @consumer_secret
79
+ config.oauth_token = @oauth_token
80
+ config.oauth_token_secret = @oauth_token_secret
81
+ end
82
+ @twitter_client = ::Twitter.client
83
+ end
84
+
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,67 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Storage
5
+ class Base
6
+ include Backup::Configuration::Helpers
7
+
8
+ ##
9
+ # The time when the backup initiated (in format: 2011.02.20.03.29.59)
10
+ attr_accessor :time
11
+
12
+ ##
13
+ # Sets the limit to how many backups to keep in the remote location.
14
+ # If the limit exceeds it will remove the oldest backup to make room for the newest
15
+ attr_accessor :keep
16
+
17
+ ##
18
+ # Returns the local path
19
+ def local_path
20
+ TMP_PATH
21
+ end
22
+
23
+ ##
24
+ # Returns the local archive filename
25
+ def local_file
26
+ @local_file ||= File.basename(Backup::Model.file)
27
+ end
28
+
29
+ ##
30
+ # Returns the name of the file that's stored on the remote location
31
+ def remote_file
32
+ @remote_file ||= local_file
33
+ end
34
+
35
+ ##
36
+ # Provider defaults to false and will be overridden when using
37
+ # a service-based storage such as Amazon S3, Rackspace Cloud Files or Dropbox
38
+ def provider
39
+ false
40
+ end
41
+
42
+ ##
43
+ # Checks the persisted storage data by type (S3, CloudFiles, SCP, etc)
44
+ # to see if the amount of stored backups is greater than the amount of
45
+ # backups allowed. If this is the case it'll invoke the #remove! method
46
+ # on each of the oldest backups that exceed the storage limit (specified by @keep).
47
+ # After that it'll re-assign the objects variable with an array of objects that still remain
48
+ # after the removal of the older objects and files (that exceeded the @keep range). And finally
49
+ # these remaining objects will be converted to YAML format and are written back to the YAML file
50
+ def cycle!
51
+ type = self.class.name.split("::").last
52
+ storage_object = Backup::Storage::Object.new(type)
53
+ objects = [self] + storage_object.load
54
+ if keep.is_a?(Integer) and keep > 0 and objects.count > keep
55
+ objects_to_remove = objects[keep..-1]
56
+ objects_to_remove.each do |object|
57
+ Logger.message "#{ self.class } started removing (cycling) \"#{ object.remote_file }\"."
58
+ object.send(:remove!)
59
+ end
60
+ objects = objects - objects_to_remove
61
+ end
62
+ storage_object.write(objects)
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,95 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Only load the Fog gem when the Backup::Storage::CloudFiles class is loaded
5
+ Backup::Dependency.load('fog')
6
+
7
+ module Backup
8
+ module Storage
9
+ class CloudFiles < Base
10
+
11
+ ##
12
+ # Rackspace Cloud Files Credentials
13
+ attr_accessor :username, :api_key
14
+
15
+ ##
16
+ # Rackspace Cloud Files container name and path
17
+ attr_accessor :container, :path
18
+
19
+ ##
20
+ # Creates a new instance of the Rackspace Cloud Files storage object
21
+ # First it sets the defaults (if any exist) and then evaluates
22
+ # the configuration block which may overwrite these defaults
23
+ def initialize(&block)
24
+ load_defaults!
25
+
26
+ @path ||= 'backups'
27
+
28
+ instance_eval(&block) if block_given?
29
+
30
+ @time = TIME
31
+ end
32
+
33
+ ##
34
+ # This is the remote path to where the backup files will be stored
35
+ def remote_path
36
+ File.join(path, TRIGGER)
37
+ end
38
+
39
+ ##
40
+ # This is the provider that Fog uses for the Cloud Files Storage
41
+ def provider
42
+ 'Rackspace'
43
+ end
44
+
45
+ ##
46
+ # Performs the backup transfer
47
+ def perform!
48
+ transfer!
49
+ cycle!
50
+ end
51
+
52
+ private
53
+
54
+ ##
55
+ # Establishes a connection to Rackspace Cloud Files and returns the Fog object.
56
+ # Not doing any instance variable caching because this object gets persisted in YAML
57
+ # format to a file and will issues. This, however has no impact on performance since it only
58
+ # gets invoked once per object for a #transfer! and once for a remove! Backups run in the
59
+ # background anyway so even if it were a bit slower it shouldn't matter.
60
+ def connection
61
+ Fog::Storage.new(
62
+ :provider => provider,
63
+ :rackspace_username => username,
64
+ :rackspace_api_key => api_key
65
+ )
66
+ end
67
+
68
+ ##
69
+ # Transfers the archived file to the specified Cloud Files container
70
+ def transfer!
71
+ begin
72
+ Logger.message("#{ self.class } started transferring \"#{ remote_file }\".")
73
+ connection.put_object(
74
+ container,
75
+ File.join(remote_path, remote_file),
76
+ File.open(File.join(local_path, local_file))
77
+ )
78
+ rescue Excon::Errors::SocketError => e
79
+ puts "\nAn error occurred while trying to transfer the backup."
80
+ puts "Make sure the container exists and try again.\n\n"
81
+ exit
82
+ end
83
+ end
84
+
85
+ ##
86
+ # Removes the transferred archive file from the Cloud Files container
87
+ def remove!
88
+ begin
89
+ connection.delete_object(container, File.join(remote_path, remote_file))
90
+ rescue Excon::Errors::SocketError; end
91
+ end
92
+
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,91 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Only load the Dropbox gem when the Backup::Storage::Dropbox class is loaded
5
+ Backup::Dependency.load('dropbox')
6
+
7
+ module Backup
8
+ module Storage
9
+ class Dropbox < Base
10
+
11
+ ##
12
+ # Dropbox user credentials
13
+ attr_accessor :email, :password
14
+
15
+ ##
16
+ # Dropbox API credentials
17
+ attr_accessor :api_key, :api_secret
18
+
19
+ ##
20
+ # Path to where the backups will be stored
21
+ attr_accessor :path
22
+
23
+ ##
24
+ # Dropbox connection timeout
25
+ attr_accessor :timeout
26
+
27
+ ##
28
+ # Creates a new instance of the Dropbox storage object
29
+ # First it sets the defaults (if any exist) and then evaluates
30
+ # the configuration block which may overwrite these defaults
31
+ def initialize(&block)
32
+ load_defaults!
33
+
34
+ @path ||= 'backups'
35
+
36
+ instance_eval(&block) if block_given?
37
+
38
+ @timeout ||= 300
39
+ @time = TIME
40
+ end
41
+
42
+ ##
43
+ # This is the remote path to where the backup files will be stored
44
+ def remote_path
45
+ File.join(path, TRIGGER)
46
+ end
47
+
48
+ ##
49
+ # Performs the backup transfer
50
+ def perform!
51
+ transfer!
52
+ cycle!
53
+ end
54
+
55
+ private
56
+
57
+ ##
58
+ # Establishes a connection to Dropbox and returns the Dropbox::Session object.
59
+ # Not doing any instance variable caching because this object gets persisted in YAML
60
+ # format to a file and will issues. This, however has no impact on performance since it only
61
+ # gets invoked once per object for a #transfer! and once for a remove! Backups run in the
62
+ # background anyway so even if it were a bit slower it shouldn't matter.
63
+ def connection
64
+ session = ::Dropbox::Session.new(api_key, api_secret)
65
+ session.mode = :dropbox
66
+ session.authorizing_user = email
67
+ session.authorizing_password = password
68
+ session.authorize!
69
+ session
70
+ end
71
+
72
+ ##
73
+ # Transfers the archived file to the specified Dropbox folder
74
+ def transfer!
75
+ Logger.message("#{ self.class } started transferring \"#{ remote_file }\".")
76
+ connection.upload(File.join(local_path, local_file), remote_path, :timeout => timeout)
77
+ end
78
+
79
+ ##
80
+ # Removes the transferred archive file from the Dropbox folder
81
+ def remove!
82
+ begin
83
+ connection.delete(File.join(remote_path, remote_file))
84
+ rescue ::Dropbox::FileNotFoundError
85
+ Logger.warn "File \"#{ File.join(remote_path, remote_file) }\" does not exist, skipping removal."
86
+ end
87
+ end
88
+
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,114 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Only load the Net::FTP library/gem when the Backup::Storage::FTP class is loaded
5
+ require 'net/ftp'
6
+
7
+ module Backup
8
+ module Storage
9
+ class FTP < Base
10
+
11
+ ##
12
+ # Server credentials
13
+ attr_accessor :username, :password
14
+
15
+ ##
16
+ # Server IP Address and FTP port
17
+ attr_accessor :ip, :port
18
+
19
+ ##
20
+ # Path to store backups to
21
+ attr_accessor :path
22
+
23
+ ##
24
+ # Creates a new instance of the FTP storage object
25
+ # First it sets the defaults (if any exist) and then evaluates
26
+ # the configuration block which may overwrite these defaults
27
+ def initialize(&block)
28
+ load_defaults!
29
+
30
+ @port ||= 21
31
+ @path ||= 'backups'
32
+
33
+ instance_eval(&block) if block_given?
34
+
35
+ @time = TIME
36
+ @path = path.sub(/^\~\//, '')
37
+ end
38
+
39
+ ##
40
+ # This is the remote path to where the backup files will be stored
41
+ def remote_path
42
+ File.join(path, TRIGGER)
43
+ end
44
+
45
+ ##
46
+ # Performs the backup transfer
47
+ def perform!
48
+ transfer!
49
+ cycle!
50
+ end
51
+
52
+ private
53
+
54
+ ##
55
+ # Establishes a connection to the remote server and returns the Net::FTP object.
56
+ # Not doing any instance variable caching because this object gets persisted in YAML
57
+ # format to a file and will issues. This, however has no impact on performance since it only
58
+ # gets invoked once per object for a #transfer! and once for a remove! Backups run in the
59
+ # background anyway so even if it were a bit slower it shouldn't matter.
60
+ #
61
+ # Note *
62
+ # Since the FTP port is defined as a constant in the Net::FTP class, and might be required
63
+ # to change by the user, we dynamically remove and re-add the constant with the provided port value
64
+ def connection
65
+ if defined? Net::FTP::FTP_PORT
66
+ Net::FTP.send(:remove_const, :FTP_PORT)
67
+ end; Net::FTP.send(:const_set, :FTP_PORT, port)
68
+
69
+ Net::FTP.new(ip, username, password)
70
+ end
71
+
72
+ ##
73
+ # Transfers the archived file to the specified remote server
74
+ def transfer!
75
+ Logger.message("#{ self.class } started transferring \"#{ remote_file }\".")
76
+ create_remote_directories!
77
+ connection.put(
78
+ File.join(local_path, local_file),
79
+ File.join(remote_path, remote_file)
80
+ )
81
+ end
82
+
83
+ ##
84
+ # Removes the transferred archive file from the server
85
+ def remove!
86
+ begin
87
+ connection.delete(
88
+ File.join(remote_path, remote_file)
89
+ )
90
+ rescue Net::FTPPermError
91
+ Logger.warn "Could not remove file \"#{ File.join(remote_path, remote_file) }\"."
92
+ end
93
+ end
94
+
95
+ ##
96
+ # Creates (if they don't exist yet) all the directories on the remote
97
+ # server in order to upload the backup file. Net::FTP does not support
98
+ # paths to directories that don't yet exist when creating new directories.
99
+ # Instead, we split the parts up in to an array (for each '/') and loop through
100
+ # that to create the directories one by one. Net::FTP raises an exception when
101
+ # the directory it's trying ot create already exists, so we have rescue it
102
+ def create_remote_directories!
103
+ path_parts = Array.new
104
+ remote_path.split('/').each do |path_part|
105
+ path_parts << path_part
106
+ begin
107
+ connection.mkdir(path_parts.join('/'))
108
+ rescue Net::FTPPermError; end
109
+ end
110
+ end
111
+
112
+ end
113
+ end
114
+ end