backup 3.0.20 → 3.0.21

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 (178) hide show
  1. data/Gemfile +1 -5
  2. data/Gemfile.lock +46 -50
  3. data/README.md +54 -27
  4. data/lib/backup.rb +16 -39
  5. data/lib/backup/archive.rb +42 -18
  6. data/lib/backup/cleaner.rb +110 -25
  7. data/lib/backup/cli/helpers.rb +17 -32
  8. data/lib/backup/cli/utility.rb +46 -107
  9. data/lib/backup/compressor/base.rb +14 -2
  10. data/lib/backup/compressor/bzip2.rb +10 -24
  11. data/lib/backup/compressor/gzip.rb +10 -24
  12. data/lib/backup/compressor/lzma.rb +10 -23
  13. data/lib/backup/compressor/pbzip2.rb +12 -32
  14. data/lib/backup/config.rb +171 -0
  15. data/lib/backup/configuration/compressor/base.rb +1 -2
  16. data/lib/backup/configuration/compressor/pbzip2.rb +4 -4
  17. data/lib/backup/configuration/database/base.rb +2 -1
  18. data/lib/backup/configuration/database/mongodb.rb +8 -0
  19. data/lib/backup/configuration/database/mysql.rb +4 -0
  20. data/lib/backup/configuration/database/postgresql.rb +4 -0
  21. data/lib/backup/configuration/database/redis.rb +4 -0
  22. data/lib/backup/configuration/database/riak.rb +5 -1
  23. data/lib/backup/configuration/encryptor/base.rb +1 -2
  24. data/lib/backup/configuration/encryptor/open_ssl.rb +1 -1
  25. data/lib/backup/configuration/helpers.rb +7 -2
  26. data/lib/backup/configuration/notifier/base.rb +4 -28
  27. data/lib/backup/configuration/storage/base.rb +1 -1
  28. data/lib/backup/configuration/storage/dropbox.rb +14 -4
  29. data/lib/backup/configuration/syncer/base.rb +10 -0
  30. data/lib/backup/configuration/syncer/rsync/base.rb +28 -0
  31. data/lib/backup/configuration/syncer/rsync/local.rb +11 -0
  32. data/lib/backup/configuration/syncer/rsync/pull.rb +11 -0
  33. data/lib/backup/configuration/syncer/rsync/push.rb +31 -0
  34. data/lib/backup/configuration/syncer/s3.rb +0 -4
  35. data/lib/backup/database/base.rb +25 -7
  36. data/lib/backup/database/mongodb.rb +112 -75
  37. data/lib/backup/database/mysql.rb +54 -29
  38. data/lib/backup/database/postgresql.rb +60 -42
  39. data/lib/backup/database/redis.rb +61 -39
  40. data/lib/backup/database/riak.rb +35 -11
  41. data/lib/backup/dependency.rb +4 -5
  42. data/lib/backup/encryptor/base.rb +13 -1
  43. data/lib/backup/encryptor/gpg.rb +39 -39
  44. data/lib/backup/encryptor/open_ssl.rb +28 -38
  45. data/lib/backup/logger.rb +20 -11
  46. data/lib/backup/model.rb +206 -163
  47. data/lib/backup/notifier/base.rb +27 -25
  48. data/lib/backup/notifier/campfire.rb +7 -13
  49. data/lib/backup/notifier/hipchat.rb +28 -28
  50. data/lib/backup/notifier/mail.rb +24 -26
  51. data/lib/backup/notifier/presently.rb +10 -18
  52. data/lib/backup/notifier/prowl.rb +9 -17
  53. data/lib/backup/notifier/twitter.rb +11 -18
  54. data/lib/backup/package.rb +47 -0
  55. data/lib/backup/packager.rb +81 -16
  56. data/lib/backup/splitter.rb +48 -35
  57. data/lib/backup/storage/base.rb +44 -172
  58. data/lib/backup/storage/cloudfiles.rb +31 -46
  59. data/lib/backup/storage/cycler.rb +117 -0
  60. data/lib/backup/storage/dropbox.rb +92 -76
  61. data/lib/backup/storage/ftp.rb +30 -40
  62. data/lib/backup/storage/local.rb +44 -45
  63. data/lib/backup/storage/ninefold.rb +55 -49
  64. data/lib/backup/storage/rsync.rb +49 -56
  65. data/lib/backup/storage/s3.rb +33 -44
  66. data/lib/backup/storage/scp.rb +21 -48
  67. data/lib/backup/storage/sftp.rb +26 -40
  68. data/lib/backup/syncer/base.rb +7 -0
  69. data/lib/backup/syncer/rsync/base.rb +78 -0
  70. data/lib/backup/syncer/rsync/local.rb +53 -0
  71. data/lib/backup/syncer/rsync/pull.rb +38 -0
  72. data/lib/backup/syncer/rsync/push.rb +113 -0
  73. data/lib/backup/syncer/s3.rb +42 -32
  74. data/lib/backup/version.rb +1 -1
  75. data/spec/archive_spec.rb +235 -69
  76. data/spec/cleaner_spec.rb +304 -0
  77. data/spec/cli/helpers_spec.rb +142 -1
  78. data/spec/cli/utility_spec.rb +338 -13
  79. data/spec/compressor/base_spec.rb +31 -0
  80. data/spec/compressor/bzip2_spec.rb +60 -35
  81. data/spec/compressor/gzip_spec.rb +60 -35
  82. data/spec/compressor/lzma_spec.rb +60 -35
  83. data/spec/compressor/pbzip2_spec.rb +98 -37
  84. data/spec/config_spec.rb +321 -0
  85. data/spec/configuration/base_spec.rb +4 -4
  86. data/spec/configuration/compressor/bzip2_spec.rb +1 -0
  87. data/spec/configuration/compressor/gzip_spec.rb +1 -0
  88. data/spec/configuration/compressor/lzma_spec.rb +1 -0
  89. data/spec/configuration/compressor/pbzip2_spec.rb +32 -0
  90. data/spec/configuration/database/base_spec.rb +2 -1
  91. data/spec/configuration/database/mongodb_spec.rb +26 -16
  92. data/spec/configuration/database/mysql_spec.rb +4 -0
  93. data/spec/configuration/database/postgresql_spec.rb +4 -0
  94. data/spec/configuration/database/redis_spec.rb +4 -0
  95. data/spec/configuration/database/riak_spec.rb +4 -0
  96. data/spec/configuration/encryptor/gpg_spec.rb +1 -0
  97. data/spec/configuration/encryptor/open_ssl_spec.rb +1 -0
  98. data/spec/configuration/notifier/base_spec.rb +32 -0
  99. data/spec/configuration/notifier/campfire_spec.rb +1 -0
  100. data/spec/configuration/notifier/hipchat_spec.rb +1 -0
  101. data/spec/configuration/notifier/mail_spec.rb +1 -0
  102. data/spec/configuration/notifier/presently_spec.rb +1 -0
  103. data/spec/configuration/notifier/prowl_spec.rb +1 -0
  104. data/spec/configuration/notifier/twitter_spec.rb +1 -0
  105. data/spec/configuration/storage/cloudfiles_spec.rb +1 -0
  106. data/spec/configuration/storage/dropbox_spec.rb +4 -3
  107. data/spec/configuration/storage/ftp_spec.rb +1 -0
  108. data/spec/configuration/storage/local_spec.rb +1 -0
  109. data/spec/configuration/storage/ninefold_spec.rb +1 -0
  110. data/spec/configuration/storage/rsync_spec.rb +3 -1
  111. data/spec/configuration/storage/s3_spec.rb +1 -0
  112. data/spec/configuration/storage/scp_spec.rb +1 -0
  113. data/spec/configuration/storage/sftp_spec.rb +1 -0
  114. data/spec/configuration/syncer/rsync/base_spec.rb +33 -0
  115. data/spec/configuration/syncer/rsync/local_spec.rb +10 -0
  116. data/spec/configuration/syncer/rsync/pull_spec.rb +10 -0
  117. data/spec/configuration/syncer/{rsync_spec.rb → rsync/push_spec.rb} +12 -15
  118. data/spec/configuration/syncer/s3_spec.rb +2 -3
  119. data/spec/database/base_spec.rb +35 -20
  120. data/spec/database/mongodb_spec.rb +298 -119
  121. data/spec/database/mysql_spec.rb +147 -72
  122. data/spec/database/postgresql_spec.rb +155 -100
  123. data/spec/database/redis_spec.rb +200 -97
  124. data/spec/database/riak_spec.rb +82 -24
  125. data/spec/dependency_spec.rb +49 -0
  126. data/spec/encryptor/base_spec.rb +30 -0
  127. data/spec/encryptor/gpg_spec.rb +105 -28
  128. data/spec/encryptor/open_ssl_spec.rb +85 -114
  129. data/spec/logger_spec.rb +74 -8
  130. data/spec/model_spec.rb +528 -220
  131. data/spec/notifier/base_spec.rb +89 -0
  132. data/spec/notifier/campfire_spec.rb +147 -119
  133. data/spec/notifier/hipchat_spec.rb +140 -145
  134. data/spec/notifier/mail_spec.rb +190 -248
  135. data/spec/notifier/presently_spec.rb +147 -282
  136. data/spec/notifier/prowl_spec.rb +79 -111
  137. data/spec/notifier/twitter_spec.rb +87 -106
  138. data/spec/package_spec.rb +61 -0
  139. data/spec/packager_spec.rb +154 -0
  140. data/spec/spec_helper.rb +36 -13
  141. data/spec/splitter_spec.rb +90 -41
  142. data/spec/storage/base_spec.rb +95 -239
  143. data/spec/storage/cloudfiles_spec.rb +185 -75
  144. data/spec/storage/cycler_spec.rb +239 -0
  145. data/spec/storage/dropbox_spec.rb +318 -87
  146. data/spec/storage/ftp_spec.rb +165 -152
  147. data/spec/storage/local_spec.rb +206 -54
  148. data/spec/storage/ninefold_spec.rb +264 -128
  149. data/spec/storage/rsync_spec.rb +244 -163
  150. data/spec/storage/s3_spec.rb +175 -64
  151. data/spec/storage/scp_spec.rb +156 -150
  152. data/spec/storage/sftp_spec.rb +153 -135
  153. data/spec/syncer/base_spec.rb +22 -0
  154. data/spec/syncer/rsync/base_spec.rb +118 -0
  155. data/spec/syncer/rsync/local_spec.rb +121 -0
  156. data/spec/syncer/rsync/pull_spec.rb +90 -0
  157. data/spec/syncer/rsync/push_spec.rb +327 -0
  158. data/spec/syncer/s3_spec.rb +180 -91
  159. data/templates/cli/utility/config +1 -1
  160. data/templates/cli/utility/database/mongodb +4 -0
  161. data/templates/cli/utility/database/mysql +3 -0
  162. data/templates/cli/utility/database/postgresql +3 -0
  163. data/templates/cli/utility/database/redis +3 -0
  164. data/templates/cli/utility/database/riak +3 -0
  165. data/templates/cli/utility/storage/dropbox +4 -1
  166. data/templates/cli/utility/syncer/rsync_local +12 -0
  167. data/templates/cli/utility/syncer/{rsync → rsync_pull} +2 -2
  168. data/templates/cli/utility/syncer/rsync_push +17 -0
  169. data/templates/storage/dropbox/authorization_url.erb +1 -1
  170. metadata +42 -17
  171. data/lib/backup/configuration/syncer/rsync.rb +0 -45
  172. data/lib/backup/finder.rb +0 -87
  173. data/lib/backup/storage/object.rb +0 -47
  174. data/lib/backup/syncer/rsync.rb +0 -152
  175. data/spec/backup_spec.rb +0 -11
  176. data/spec/finder_spec.rb +0 -91
  177. data/spec/storage/object_spec.rb +0 -74
  178. data/spec/syncer/rsync_spec.rb +0 -195
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ class Package
5
+
6
+ ##
7
+ # The time when the backup initiated (in format: 2011.02.20.03.29.59)
8
+ attr_reader :time
9
+
10
+ ##
11
+ # The trigger which initiated the backup process
12
+ attr_reader :trigger
13
+
14
+ ##
15
+ # Extension for the final archive file(s)
16
+ attr_accessor :extension
17
+
18
+ ##
19
+ # Set by the Splitter if the final archive was "chunked"
20
+ attr_accessor :chunk_suffixes
21
+
22
+ ##
23
+ # The version of Backup used to create the package
24
+ attr_reader :version
25
+
26
+ def initialize(model)
27
+ @time = model.time
28
+ @trigger = model.trigger
29
+ @extension = 'tar'
30
+ @chunk_suffixes = Array.new
31
+ @version = Backup::Version.current
32
+ end
33
+
34
+ def filenames
35
+ if chunk_suffixes.empty?
36
+ [basename]
37
+ else
38
+ chunk_suffixes.map {|suffix| "#{ basename }-#{ suffix }" }
39
+ end
40
+ end
41
+
42
+ def basename
43
+ "#{ time }.#{ trigger }.#{ extension }"
44
+ end
45
+
46
+ end
47
+ end
@@ -1,25 +1,90 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Backup
4
- class Packager
5
- include Backup::CLI::Helpers
4
+ module Packager
5
+ class << self
6
+ include Backup::CLI::Helpers
6
7
 
7
- ##
8
- # Holds an instance of the current Backup model
9
- attr_accessor :model
8
+ ##
9
+ # Build the final package for the backup model.
10
+ def package!(model)
11
+ @package = model.package
12
+ @encryptor = model.encryptor
13
+ @splitter = model.splitter
10
14
 
11
- ##
12
- # Creates a new instance of the Backup::Packager class
13
- def initialize(model)
14
- @model = model
15
- end
15
+ Logger.message "Packaging the backup files..."
16
+ procedure.call
17
+ Logger.message "Packaging Complete!"
18
+ end
16
19
 
17
- ##
18
- # Packages the current state of the backup in to a single archived file.
19
- def package!
20
- Logger.message "#{ self.class } started packaging the backup files."
21
- run("#{ utility(:tar) } -c -f '#{ File.join(Backup::TMP_PATH, "#{ Backup::TIME }.#{ Backup::TRIGGER }.tar") }' -C '#{ Backup::TMP_PATH }' '#{ Backup::TRIGGER }'")
22
- end
20
+ private
21
+
22
+ ##
23
+ # Builds a chain of nested Procs which assemble and execute
24
+ # the final command to package the backup.
25
+ # This is done so that the Encryptor and Splitter have the ability
26
+ # to perform actions before and after the final command is executed.
27
+ # No Encryptors currently utilize this, however the Splitter does.
28
+ def procedure
29
+ stack = []
30
+
31
+ ##
32
+ # Initial `tar` command to package the temporary backup folder.
33
+ # The command's output will then be either piped to the Encryptor
34
+ # or the Splitter (if no Encryptor), or redirected into the final
35
+ # output file if neither are configured.
36
+ @package_command = "#{ utility(:tar) } -cf - " +
37
+ "-C '#{ Config.tmp_path }' '#{ @package.trigger }'"
38
+
39
+ ##
40
+ # If an Encryptor was configured, it will be called first
41
+ # to amend the command to be piped through the encryption utility.
42
+ # It's output will then be either piped into a Splitter, or sent
43
+ # directly to the final output file.
44
+ if @encryptor
45
+ stack << lambda do
46
+ @encryptor.encrypt_with do |command, ext|
47
+ @package_command << " | #{command}"
48
+ @package.extension << ext
49
+ stack.shift.call
50
+ end
51
+ end
52
+ end
23
53
 
54
+ ##
55
+ # If a Splitter was configured, the command will be piped through
56
+ # the `split` command. Once the Proc executing the final command
57
+ # has completed and returns back to the Splitter, it will check the
58
+ # final output files to determine if the backup was indeed split.
59
+ # If so, it will set the package's chunk_suffixes. If not, it will
60
+ # remove the '-aa' suffix from the only file created by `split`.
61
+ #
62
+ # If no Splitter was configured, the command output will be
63
+ # redirected directly into the final output file.
64
+ if @splitter
65
+ stack << lambda do
66
+ @splitter.split_with do |command|
67
+ @package_command << " | #{command}"
68
+ stack.shift.call
69
+ end
70
+ end
71
+ else
72
+ stack << lambda do
73
+ outfile = File.join(Config.tmp_path, @package.basename)
74
+ @package_command << " > #{ outfile }"
75
+ stack.shift.call
76
+ end
77
+ end
78
+
79
+ ##
80
+ # Last Proc to be called runs the command the procedure built.
81
+ # Once complete, the call stack will unwind back through the
82
+ # preceeding Procs in the stack (if any)
83
+ stack << lambda { run(@package_command) }
84
+
85
+ stack.shift
86
+ end
87
+
88
+ end
24
89
  end
25
90
  end
@@ -4,58 +4,71 @@ module Backup
4
4
  class Splitter
5
5
  include Backup::CLI::Helpers
6
6
 
7
- ##
8
- # Separates the end of the file from the chunk extension name
9
- SUFFIX_SEPARATOR = "-"
7
+ def initialize(model, chunk_size)
8
+ @model = model
9
+ @chunk_size = chunk_size
10
+ end
10
11
 
11
12
  ##
12
- # Holds an instance of the current Backup model
13
- attr_accessor :model
13
+ # This is called as part of the procedure used to build the final
14
+ # backup package file(s). It yields it's portion of the command line
15
+ # for this procedure, which will split the data being piped into it
16
+ # into multiple files, based on the @chunk_size.
17
+ # Once the packaging procedure is complete, it will return and
18
+ # @package.chunk_suffixes will be set based on the resulting files.
19
+ def split_with
20
+ before_packaging
21
+ yield @split_command
22
+ after_packaging
23
+ end
24
+
25
+ private
14
26
 
15
27
  ##
16
- # Instantiates a new instance of Backup::Splitter and takes
17
- # a Backup model as an argument.
18
- # Also, (re)set the Backup::Model.chunk_suffixes to an empty array.
19
- def initialize(model)
20
- @model = model
21
- Backup::Model.chunk_suffixes = Array.new
28
+ # The `split` command reads from $stdin and will store it's output in
29
+ # multiple files, based on the @chunk_size. The files will be
30
+ # written using the given `prefix`, which is the full path to the
31
+ # final @package.basename, plus a '-' separator. This `prefix` will then
32
+ # be suffixed using 'aa', 'ab', and so on... for each file.
33
+ def before_packaging
34
+ @package = @model.package
35
+ Logger.message "Splitter configured with a chunk size of " +
36
+ "#{ @chunk_size }MB."
37
+
38
+ @split_command = "#{ utility(:split) } -b #{ @chunk_size }m - " +
39
+ "'#{ File.join(Config.tmp_path, @package.basename + '-') }'"
22
40
  end
23
41
 
24
42
  ##
25
- # Splits the file in multiple chunks if necessary, and it's necessary
26
- # when the requested chunk size is smaller than the actual backup file
27
- def split!
28
- return unless model.chunk_size.is_a?(Integer)
29
-
30
- if File.size(model.file) > bytes_representation_of(model.chunk_size)
31
- Logger.message "#{ self.class } started splitting the packaged archive in to chunks of #{ model.chunk_size } megabytes."
32
- run("#{ utility(:split) } -b #{ model.chunk_size }m '#{ model.file }' '#{ model.file + SUFFIX_SEPARATOR }'")
33
- Backup::Model.chunk_suffixes = chunk_suffixes
43
+ # Finds the resulting files from the packaging procedure
44
+ # and stores an Array of suffixes used in @package.chunk_suffixes.
45
+ # If the @chunk_size was never reached and only one file
46
+ # was written, that file will be suffixed with '-aa'.
47
+ # In which case, it will simply remove the suffix from the filename.
48
+ def after_packaging
49
+ suffixes = chunk_suffixes
50
+ if suffixes == ['aa']
51
+ FileUtils.mv(
52
+ File.join(Config.tmp_path, @package.basename + '-aa'),
53
+ File.join(Config.tmp_path, @package.basename)
54
+ )
55
+ else
56
+ @package.chunk_suffixes = suffixes
34
57
  end
35
58
  end
36
59
 
37
- private
38
-
39
60
  ##
40
- # Returns an array of suffixes for each chunk.
41
- # For example: [aa, ab, ac, ad, ae] - Chunk suffixes are sorted on alphabetical order
61
+ # Returns an array of suffixes for each chunk, in alphabetical order.
62
+ # For example: [aa, ab, ac, ad, ae]
42
63
  def chunk_suffixes
43
- chunks.map do |chunk|
44
- File.extname(chunk).split("-").last
45
- end.sort
64
+ chunks.map {|chunk| File.extname(chunk).split('-').last }.sort
46
65
  end
47
66
 
48
67
  ##
49
68
  # Returns an array of full paths to the backup chunks.
50
- # Chunks aresorted on alphabetical order
69
+ # Chunks are sorted in alphabetical order.
51
70
  def chunks
52
- Dir["#{model.file}-*"].sort
53
- end
54
-
55
- ##
56
- # Converts the provided megabytes to a bytes representation
57
- def bytes_representation_of(megabytes)
58
- megabytes * 1024 * 1024
71
+ Dir[File.join(Config.tmp_path, @package.basename + '-*')].sort
59
72
  end
60
73
 
61
74
  end
@@ -5,107 +5,36 @@ module Backup
5
5
  class Base
6
6
  include Backup::Configuration::Helpers
7
7
 
8
- ##
9
- # The time when the backup initiated (in format: 2011.02.20.03.29.59)
10
- attr_accessor :time
11
-
12
8
  ##
13
9
  # Sets the limit to how many backups to keep in the remote location.
14
10
  # If exceeded, the oldest will be removed to make room for the newest
15
11
  attr_accessor :keep
16
12
 
17
- # Temporarily holds the configuration block used to instantiate the
18
- # storage object. Used for updating storage objects loaded from YAML
19
- # during backup rotation in #cycle!
20
- attr_accessor :configure_block
21
-
22
- ##
23
- # Contains an array of chunk suffixes (if any)
24
- # If none are set, this will be an empty array, in which case Backup assumes
25
- # we haven't been splitting the backup in to multiple chunks. The storage object
26
- # will only attempt to transfer/remove chunks if this array contains chunk suffixes.
27
- attr_accessor :chunk_suffixes
28
-
29
- ##
30
- # Super method for the child classes' perform! method. "super" should
31
- # always be invoked from the child classes' perform! method to ensure that the
32
- # @chunk_suffixes array gets set to the storage object, which will be used to transfer all the
33
- # chunks to the remote location, rather than the single backup file. Also, this will be persisted
34
- # and loaded back in during the cycling process, so it gets properly deleted from the remote location.
35
-
36
13
  ##
37
14
  # (Optional)
38
- # User-defined string used to uniquely identify multiple storages of the same type.
39
- # This will be appended to the YAML storage file used for cycling backups.
15
+ # 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.
40
18
  attr_accessor :storage_id
41
19
 
42
- ##
43
- # Set to Backup::Version.current just before the object is stored
44
- # in the YAML file for cycling. This way, we know when the object
45
- # is loaded from the YAML file, which version of Backup stored it.
46
- attr_reader :version
47
-
48
- def perform!
49
- @chunk_suffixes ||= Backup::Model.chunk_suffixes
50
- end
51
-
52
20
  ##
53
21
  # Creates a new instance of the storage object
54
- def initialize(storage_id = nil, &block)
55
- @configure_block = block
22
+ # * Called with super(model, storage_id) from each subclass
23
+ def initialize(model, storage_id = nil)
24
+ load_defaults!
25
+ @model = model
56
26
  @storage_id = storage_id
57
- configure!
58
27
  end
59
28
 
60
29
  ##
61
- # Return the storage name, with optional storage_id
62
- def storage_name
63
- self.class.to_s.sub('Backup::', '') +
64
- (storage_id ? " (#{storage_id})" : '')
65
- end
66
-
67
- ##
68
- # Returns the full filename of the processed backup file
69
- def filename
70
- @filename ||= File.basename(Backup::Model.file)
71
- end
72
-
73
- ##
74
- # Returns the local path
75
- def local_path
76
- TMP_PATH
77
- end
78
-
79
- ##
80
- # Returns an array of backup chunks
81
- def chunks
82
- chunk_suffixes.map do |chunk_suffix|
83
- "#{ filename }-#{ chunk_suffix }"
84
- end.sort
85
- end
86
-
87
- ##
88
- # Returns a block with two arguments: "local_file, remote_file"
89
- # The local_file is the full file name: "2011.08.30.11.00.02.backup.tar.gz.enc"
90
- # The remote_file is the full file name, minus the timestamp: "backup.tar.gz.enc"
91
- def files_to_transfer
92
- if chunks?
93
- chunks.each do |chunk|
94
- yield chunk, chunk[20..-1]
95
- end
96
- else
97
- yield filename, filename[20..-1]
98
- end
30
+ # Performs the backup transfer
31
+ def perform!
32
+ @package = @model.package
33
+ transfer!
34
+ cycle!
99
35
  end
100
36
 
101
- alias :transferred_files :files_to_transfer
102
-
103
- ##
104
- # Returns true if we're working with chunks
105
- # that were splitted by Backup
106
- def chunks?
107
- chunk_suffixes.is_a?(Array) and chunk_suffixes.count > 0
108
- end
37
+ private
109
38
 
110
39
  ##
111
40
  # Provider defaults to false. Overridden when using a service-based
@@ -114,112 +43,55 @@ module Backup
114
43
  false
115
44
  end
116
45
 
117
- private
118
-
119
- ##
120
- # Configure the storage object, using optional configuration block
121
- # Uses #pre_configure to set defaults (if any exist) and then evaluates
122
- # the optional configuration block which may overwrite these defaults.
123
- # Then uses #post_configure to adjust the configuration as needed.
124
- #
125
- # This method is also used to update storage objects loaded from the
126
- # YAML data storage file used for backup rotation in #cycle!
127
- def configure!
128
- pre_configure
129
- instance_eval(&@configure_block) if @configure_block
130
- post_configure
131
- self
132
- end
133
-
134
46
  ##
135
- # Set configuration defaults before evaluating configuration block.
136
- # Each subclass may perform additional actions after calling super()
137
- def pre_configure
138
- load_defaults!
139
- end
47
+ # Each subclass must define a +path+ where remote files will be stored
48
+ def path; end
140
49
 
141
50
  ##
142
- # Adjust configuration after evaluating configuration block.
143
- # Each subclass may perform additional actions after calling super()
144
- def post_configure
145
- @time ||= TIME
51
+ # Return the storage name, with optional storage_id
52
+ def storage_name
53
+ self.class.to_s.sub('Backup::', '') +
54
+ (storage_id ? " (#{storage_id})" : '')
146
55
  end
147
56
 
148
57
  ##
149
- # Update the configuration with the given +configure_block+
150
- # This is to update the configuration for this storage object
151
- # once it's been loaded from the YAML storage file (within #cycle!)
152
- # so that cycling operations can be performed using the latest
153
- # configuration from the current backup job.
154
- def update!(configure_block)
155
- upgrade_if_needed!
156
- instance_exec(configure_block) do |block|
157
- @configure_block = block; configure!
158
- end
58
+ # Returns the local path
59
+ # This is where any Package to be transferred is located.
60
+ def local_path
61
+ Config.tmp_path
159
62
  end
160
63
 
161
64
  ##
162
- # Upgrades the format of an object loaded from the YAML storage file
163
- # if it was stored with a previous, incompatible version of Backup,
164
- # before it is updated using the new configure_block in #update!
165
- def upgrade_if_needed!
166
- return if version == Backup::Version.current
167
- case
168
- when version.nil? # <= 3.0.19
169
- @filename = @remote_file
170
- @chunk_suffixes = []
171
- clean!
172
- else; # upgrade not required
173
- end
65
+ # Returns the remote path for the given Package
66
+ # This is where the Package will be stored, or was previously stored.
67
+ def remote_path_for(package)
68
+ File.join(path, package.trigger, package.time)
174
69
  end
175
70
 
176
71
  ##
177
- # Clear all attributes except those which need to be stored
178
- # in the YAML storage file for cycling, and version stamp it.
179
- def clean!
180
- stored_attrs = [:@filename, :@time, :@chunk_suffixes]
181
- (instance_variables.map(&:to_sym) - stored_attrs).each do |var|
182
- remove_instance_variable var
72
+ # Yields two arguments to the given block: "local_file, remote_file"
73
+ # The local_file is the full file name:
74
+ # e.g. "2011.08.30.11.00.02.backup.tar.enc"
75
+ # The remote_file is the full file name, minus the timestamp:
76
+ # e.g. "backup.tar.enc"
77
+ def files_to_transfer_for(package)
78
+ package.filenames.each do |filename|
79
+ yield filename, filename[20..-1]
183
80
  end
184
- @version = Backup::Version.current
185
81
  end
82
+ alias :transferred_files_for :files_to_transfer_for
186
83
 
187
84
  ##
188
- # Checks the persisted storage data by type (S3, CloudFiles, SCP, etc)
189
- # to see if the amount of stored backups is greater than the amount of
190
- # backups allowed. If this is the case it'll invoke the #remove! method
191
- # on each of the oldest backups that exceed the storage limit (specified
192
- # by @keep). After that it'll re-assign the objects variable with an
193
- # array of objects that still remain after the removal of the older
194
- # objects and files (that exceeded the @keep range). And finally these
195
- # remaining objects will be converted to YAML format and are written back
196
- # to the YAML file.
197
- # Each remaining storage object's attributes will be updated using the
198
- # defaults and configuration block defined for the current backup job
199
- # in case the storage location is changed or credentials are updated.
85
+ # Adds the current package being stored to the YAML cycle data file
86
+ # and will remove any old Package file(s) when the storage limit
87
+ # set by #keep is exceeded. Any errors raised while attempting to
88
+ # remove older packages will be rescued and a warning will be logged
89
+ # containing the original error message.
200
90
  def cycle!
201
91
  return unless keep.to_i > 0
202
- type = self.class.name.split("::").last
203
- storage_object = Backup::Storage::Object.new(type, storage_id)
204
- objects = storage_object.load
205
- objects.each {|object| object.send(:update!, @configure_block) }
206
- objects.unshift(self)
207
- if objects.count > keep
208
- objects_to_remove = objects[keep..-1]
209
- objects_to_remove.each do |object|
210
- Logger.message "#{storage_name} started removing (cycling) " +
211
- "'#{ object.filename }'."
212
- begin
213
- object.send(:remove!)
214
- rescue => err
215
- Logger.warn Errors::Storage::CycleError.wrap(err,
216
- "#{storage_name} failed to remove '#{object.filename}'")
217
- end
218
- end
219
- objects = objects - objects_to_remove
220
- end
221
- objects.each {|object| object.send(:clean!) }
222
- storage_object.write(objects)
92
+ Logger.message "#{ storage_name }: Cycling Started..."
93
+ Cycler.cycle!(self, @package)
94
+ Logger.message "#{ storage_name }: Cycling Complete!"
223
95
  end
224
96
 
225
97
  end