backup_checksum 3.0.23

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 (244) hide show
  1. data/.gitignore +7 -0
  2. data/.travis.yml +10 -0
  3. data/Gemfile +28 -0
  4. data/Gemfile.lock +130 -0
  5. data/Guardfile +21 -0
  6. data/LICENSE.md +24 -0
  7. data/README.md +476 -0
  8. data/backup_checksum.gemspec +32 -0
  9. data/bin/backup +11 -0
  10. data/lib/backup.rb +217 -0
  11. data/lib/backup/archive.rb +117 -0
  12. data/lib/backup/binder.rb +22 -0
  13. data/lib/backup/checksum/base.rb +44 -0
  14. data/lib/backup/checksum/shasum.rb +16 -0
  15. data/lib/backup/cleaner.rb +121 -0
  16. data/lib/backup/cli/helpers.rb +88 -0
  17. data/lib/backup/cli/utility.rb +247 -0
  18. data/lib/backup/compressor/base.rb +29 -0
  19. data/lib/backup/compressor/bzip2.rb +50 -0
  20. data/lib/backup/compressor/gzip.rb +47 -0
  21. data/lib/backup/compressor/lzma.rb +50 -0
  22. data/lib/backup/compressor/pbzip2.rb +56 -0
  23. data/lib/backup/config.rb +173 -0
  24. data/lib/backup/configuration/base.rb +15 -0
  25. data/lib/backup/configuration/checksum/base.rb +9 -0
  26. data/lib/backup/configuration/checksum/shasum.rb +9 -0
  27. data/lib/backup/configuration/compressor/base.rb +9 -0
  28. data/lib/backup/configuration/compressor/bzip2.rb +23 -0
  29. data/lib/backup/configuration/compressor/gzip.rb +23 -0
  30. data/lib/backup/configuration/compressor/lzma.rb +23 -0
  31. data/lib/backup/configuration/compressor/pbzip2.rb +28 -0
  32. data/lib/backup/configuration/database/base.rb +19 -0
  33. data/lib/backup/configuration/database/mongodb.rb +49 -0
  34. data/lib/backup/configuration/database/mysql.rb +42 -0
  35. data/lib/backup/configuration/database/postgresql.rb +41 -0
  36. data/lib/backup/configuration/database/redis.rb +39 -0
  37. data/lib/backup/configuration/database/riak.rb +29 -0
  38. data/lib/backup/configuration/encryptor/base.rb +9 -0
  39. data/lib/backup/configuration/encryptor/gpg.rb +17 -0
  40. data/lib/backup/configuration/encryptor/open_ssl.rb +32 -0
  41. data/lib/backup/configuration/helpers.rb +52 -0
  42. data/lib/backup/configuration/notifier/base.rb +28 -0
  43. data/lib/backup/configuration/notifier/campfire.rb +25 -0
  44. data/lib/backup/configuration/notifier/hipchat.rb +41 -0
  45. data/lib/backup/configuration/notifier/mail.rb +112 -0
  46. data/lib/backup/configuration/notifier/presently.rb +25 -0
  47. data/lib/backup/configuration/notifier/prowl.rb +23 -0
  48. data/lib/backup/configuration/notifier/twitter.rb +21 -0
  49. data/lib/backup/configuration/storage/base.rb +18 -0
  50. data/lib/backup/configuration/storage/cloudfiles.rb +25 -0
  51. data/lib/backup/configuration/storage/dropbox.rb +58 -0
  52. data/lib/backup/configuration/storage/ftp.rb +29 -0
  53. data/lib/backup/configuration/storage/local.rb +17 -0
  54. data/lib/backup/configuration/storage/ninefold.rb +20 -0
  55. data/lib/backup/configuration/storage/rsync.rb +29 -0
  56. data/lib/backup/configuration/storage/s3.rb +25 -0
  57. data/lib/backup/configuration/storage/scp.rb +25 -0
  58. data/lib/backup/configuration/storage/sftp.rb +25 -0
  59. data/lib/backup/configuration/syncer/base.rb +10 -0
  60. data/lib/backup/configuration/syncer/cloud.rb +23 -0
  61. data/lib/backup/configuration/syncer/cloud_files.rb +30 -0
  62. data/lib/backup/configuration/syncer/rsync/base.rb +28 -0
  63. data/lib/backup/configuration/syncer/rsync/local.rb +11 -0
  64. data/lib/backup/configuration/syncer/rsync/pull.rb +11 -0
  65. data/lib/backup/configuration/syncer/rsync/push.rb +31 -0
  66. data/lib/backup/configuration/syncer/s3.rb +23 -0
  67. data/lib/backup/database/base.rb +59 -0
  68. data/lib/backup/database/mongodb.rb +232 -0
  69. data/lib/backup/database/mysql.rb +163 -0
  70. data/lib/backup/database/postgresql.rb +146 -0
  71. data/lib/backup/database/redis.rb +139 -0
  72. data/lib/backup/database/riak.rb +69 -0
  73. data/lib/backup/dependency.rb +114 -0
  74. data/lib/backup/encryptor/base.rb +29 -0
  75. data/lib/backup/encryptor/gpg.rb +80 -0
  76. data/lib/backup/encryptor/open_ssl.rb +72 -0
  77. data/lib/backup/errors.rb +124 -0
  78. data/lib/backup/logger.rb +152 -0
  79. data/lib/backup/model.rb +386 -0
  80. data/lib/backup/notifier/base.rb +81 -0
  81. data/lib/backup/notifier/campfire.rb +168 -0
  82. data/lib/backup/notifier/hipchat.rb +99 -0
  83. data/lib/backup/notifier/mail.rb +206 -0
  84. data/lib/backup/notifier/presently.rb +88 -0
  85. data/lib/backup/notifier/prowl.rb +65 -0
  86. data/lib/backup/notifier/twitter.rb +70 -0
  87. data/lib/backup/package.rb +51 -0
  88. data/lib/backup/packager.rb +108 -0
  89. data/lib/backup/pipeline.rb +107 -0
  90. data/lib/backup/splitter.rb +75 -0
  91. data/lib/backup/storage/base.rb +119 -0
  92. data/lib/backup/storage/cloudfiles.rb +87 -0
  93. data/lib/backup/storage/cycler.rb +117 -0
  94. data/lib/backup/storage/dropbox.rb +181 -0
  95. data/lib/backup/storage/ftp.rb +119 -0
  96. data/lib/backup/storage/local.rb +82 -0
  97. data/lib/backup/storage/ninefold.rb +116 -0
  98. data/lib/backup/storage/rsync.rb +149 -0
  99. data/lib/backup/storage/s3.rb +94 -0
  100. data/lib/backup/storage/scp.rb +99 -0
  101. data/lib/backup/storage/sftp.rb +108 -0
  102. data/lib/backup/syncer/base.rb +42 -0
  103. data/lib/backup/syncer/cloud.rb +190 -0
  104. data/lib/backup/syncer/cloud_files.rb +56 -0
  105. data/lib/backup/syncer/rsync/base.rb +52 -0
  106. data/lib/backup/syncer/rsync/local.rb +53 -0
  107. data/lib/backup/syncer/rsync/pull.rb +38 -0
  108. data/lib/backup/syncer/rsync/push.rb +113 -0
  109. data/lib/backup/syncer/s3.rb +47 -0
  110. data/lib/backup/template.rb +46 -0
  111. data/lib/backup/version.rb +43 -0
  112. data/spec/archive_spec.rb +335 -0
  113. data/spec/cleaner_spec.rb +304 -0
  114. data/spec/cli/helpers_spec.rb +176 -0
  115. data/spec/cli/utility_spec.rb +363 -0
  116. data/spec/compressor/base_spec.rb +31 -0
  117. data/spec/compressor/bzip2_spec.rb +83 -0
  118. data/spec/compressor/gzip_spec.rb +83 -0
  119. data/spec/compressor/lzma_spec.rb +83 -0
  120. data/spec/compressor/pbzip2_spec.rb +124 -0
  121. data/spec/config_spec.rb +321 -0
  122. data/spec/configuration/base_spec.rb +35 -0
  123. data/spec/configuration/compressor/bzip2_spec.rb +29 -0
  124. data/spec/configuration/compressor/gzip_spec.rb +29 -0
  125. data/spec/configuration/compressor/lzma_spec.rb +29 -0
  126. data/spec/configuration/compressor/pbzip2_spec.rb +32 -0
  127. data/spec/configuration/database/base_spec.rb +17 -0
  128. data/spec/configuration/database/mongodb_spec.rb +56 -0
  129. data/spec/configuration/database/mysql_spec.rb +53 -0
  130. data/spec/configuration/database/postgresql_spec.rb +53 -0
  131. data/spec/configuration/database/redis_spec.rb +50 -0
  132. data/spec/configuration/database/riak_spec.rb +35 -0
  133. data/spec/configuration/encryptor/gpg_spec.rb +26 -0
  134. data/spec/configuration/encryptor/open_ssl_spec.rb +35 -0
  135. data/spec/configuration/notifier/base_spec.rb +32 -0
  136. data/spec/configuration/notifier/campfire_spec.rb +32 -0
  137. data/spec/configuration/notifier/hipchat_spec.rb +44 -0
  138. data/spec/configuration/notifier/mail_spec.rb +71 -0
  139. data/spec/configuration/notifier/presently_spec.rb +35 -0
  140. data/spec/configuration/notifier/prowl_spec.rb +29 -0
  141. data/spec/configuration/notifier/twitter_spec.rb +35 -0
  142. data/spec/configuration/storage/cloudfiles_spec.rb +41 -0
  143. data/spec/configuration/storage/dropbox_spec.rb +38 -0
  144. data/spec/configuration/storage/ftp_spec.rb +44 -0
  145. data/spec/configuration/storage/local_spec.rb +29 -0
  146. data/spec/configuration/storage/ninefold_spec.rb +32 -0
  147. data/spec/configuration/storage/rsync_spec.rb +41 -0
  148. data/spec/configuration/storage/s3_spec.rb +38 -0
  149. data/spec/configuration/storage/scp_spec.rb +41 -0
  150. data/spec/configuration/storage/sftp_spec.rb +41 -0
  151. data/spec/configuration/syncer/cloud_files_spec.rb +44 -0
  152. data/spec/configuration/syncer/rsync/base_spec.rb +33 -0
  153. data/spec/configuration/syncer/rsync/local_spec.rb +10 -0
  154. data/spec/configuration/syncer/rsync/pull_spec.rb +10 -0
  155. data/spec/configuration/syncer/rsync/push_spec.rb +43 -0
  156. data/spec/configuration/syncer/s3_spec.rb +38 -0
  157. data/spec/database/base_spec.rb +54 -0
  158. data/spec/database/mongodb_spec.rb +428 -0
  159. data/spec/database/mysql_spec.rb +335 -0
  160. data/spec/database/postgresql_spec.rb +278 -0
  161. data/spec/database/redis_spec.rb +260 -0
  162. data/spec/database/riak_spec.rb +108 -0
  163. data/spec/dependency_spec.rb +49 -0
  164. data/spec/encryptor/base_spec.rb +30 -0
  165. data/spec/encryptor/gpg_spec.rb +134 -0
  166. data/spec/encryptor/open_ssl_spec.rb +129 -0
  167. data/spec/errors_spec.rb +306 -0
  168. data/spec/logger_spec.rb +363 -0
  169. data/spec/model_spec.rb +649 -0
  170. data/spec/notifier/base_spec.rb +89 -0
  171. data/spec/notifier/campfire_spec.rb +199 -0
  172. data/spec/notifier/hipchat_spec.rb +188 -0
  173. data/spec/notifier/mail_spec.rb +280 -0
  174. data/spec/notifier/presently_spec.rb +181 -0
  175. data/spec/notifier/prowl_spec.rb +117 -0
  176. data/spec/notifier/twitter_spec.rb +132 -0
  177. data/spec/package_spec.rb +61 -0
  178. data/spec/packager_spec.rb +225 -0
  179. data/spec/pipeline_spec.rb +257 -0
  180. data/spec/spec_helper.rb +59 -0
  181. data/spec/splitter_spec.rb +120 -0
  182. data/spec/storage/base_spec.rb +160 -0
  183. data/spec/storage/cloudfiles_spec.rb +230 -0
  184. data/spec/storage/cycler_spec.rb +239 -0
  185. data/spec/storage/dropbox_spec.rb +370 -0
  186. data/spec/storage/ftp_spec.rb +247 -0
  187. data/spec/storage/local_spec.rb +235 -0
  188. data/spec/storage/ninefold_spec.rb +319 -0
  189. data/spec/storage/rsync_spec.rb +345 -0
  190. data/spec/storage/s3_spec.rb +221 -0
  191. data/spec/storage/scp_spec.rb +209 -0
  192. data/spec/storage/sftp_spec.rb +220 -0
  193. data/spec/syncer/base_spec.rb +22 -0
  194. data/spec/syncer/cloud_files_spec.rb +192 -0
  195. data/spec/syncer/rsync/base_spec.rb +118 -0
  196. data/spec/syncer/rsync/local_spec.rb +121 -0
  197. data/spec/syncer/rsync/pull_spec.rb +90 -0
  198. data/spec/syncer/rsync/push_spec.rb +327 -0
  199. data/spec/syncer/s3_spec.rb +192 -0
  200. data/spec/version_spec.rb +21 -0
  201. data/templates/cli/utility/archive +25 -0
  202. data/templates/cli/utility/compressor/bzip2 +7 -0
  203. data/templates/cli/utility/compressor/gzip +7 -0
  204. data/templates/cli/utility/compressor/lzma +7 -0
  205. data/templates/cli/utility/compressor/pbzip2 +7 -0
  206. data/templates/cli/utility/config +31 -0
  207. data/templates/cli/utility/database/mongodb +18 -0
  208. data/templates/cli/utility/database/mysql +21 -0
  209. data/templates/cli/utility/database/postgresql +17 -0
  210. data/templates/cli/utility/database/redis +16 -0
  211. data/templates/cli/utility/database/riak +11 -0
  212. data/templates/cli/utility/encryptor/gpg +12 -0
  213. data/templates/cli/utility/encryptor/openssl +9 -0
  214. data/templates/cli/utility/model.erb +23 -0
  215. data/templates/cli/utility/notifier/campfire +12 -0
  216. data/templates/cli/utility/notifier/hipchat +15 -0
  217. data/templates/cli/utility/notifier/mail +22 -0
  218. data/templates/cli/utility/notifier/presently +13 -0
  219. data/templates/cli/utility/notifier/prowl +11 -0
  220. data/templates/cli/utility/notifier/twitter +13 -0
  221. data/templates/cli/utility/splitter +7 -0
  222. data/templates/cli/utility/storage/cloud_files +22 -0
  223. data/templates/cli/utility/storage/dropbox +20 -0
  224. data/templates/cli/utility/storage/ftp +12 -0
  225. data/templates/cli/utility/storage/local +7 -0
  226. data/templates/cli/utility/storage/ninefold +9 -0
  227. data/templates/cli/utility/storage/rsync +11 -0
  228. data/templates/cli/utility/storage/s3 +19 -0
  229. data/templates/cli/utility/storage/scp +11 -0
  230. data/templates/cli/utility/storage/sftp +11 -0
  231. data/templates/cli/utility/syncer/cloud_files +48 -0
  232. data/templates/cli/utility/syncer/rsync_local +12 -0
  233. data/templates/cli/utility/syncer/rsync_pull +17 -0
  234. data/templates/cli/utility/syncer/rsync_push +17 -0
  235. data/templates/cli/utility/syncer/s3 +45 -0
  236. data/templates/general/links +11 -0
  237. data/templates/general/version.erb +2 -0
  238. data/templates/notifier/mail/failure.erb +9 -0
  239. data/templates/notifier/mail/success.erb +7 -0
  240. data/templates/notifier/mail/warning.erb +9 -0
  241. data/templates/storage/dropbox/authorization_url.erb +6 -0
  242. data/templates/storage/dropbox/authorized.erb +4 -0
  243. data/templates/storage/dropbox/cache_file_written.erb +10 -0
  244. metadata +311 -0
@@ -0,0 +1,119 @@
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
+ # use passive mode?
25
+ attr_accessor :passive_mode
26
+
27
+ ##
28
+ # Creates a new instance of the storage object
29
+ def initialize(model, storage_id = nil, &block)
30
+ super(model, storage_id)
31
+
32
+ @port ||= 21
33
+ @path ||= 'backups'
34
+ @passive_mode ||= false
35
+
36
+ instance_eval(&block) if block_given?
37
+
38
+ @path = path.sub(/^\~\//, '')
39
+ end
40
+
41
+ private
42
+
43
+ ##
44
+ # Establishes a connection to the remote server
45
+ #
46
+ # Note:
47
+ # Since the FTP port is defined as a constant in the Net::FTP class, and
48
+ # might be required to change by the user, we dynamically remove and
49
+ # re-add the constant with the provided port value
50
+ def connection
51
+ if Net::FTP.const_defined?(:FTP_PORT)
52
+ Net::FTP.send(:remove_const, :FTP_PORT)
53
+ end; Net::FTP.send(:const_set, :FTP_PORT, port)
54
+
55
+ Net::FTP.open(ip, username, password) do |ftp|
56
+ ftp.passive = true if passive_mode
57
+ yield ftp
58
+ end
59
+ end
60
+
61
+ ##
62
+ # Transfers the archived file to the specified remote server
63
+ def transfer!
64
+ remote_path = remote_path_for(@package)
65
+
66
+ connection do |ftp|
67
+ create_remote_path(remote_path, ftp)
68
+
69
+ files_to_transfer_for(@package) do |local_file, remote_file|
70
+ Logger.message "#{storage_name} started transferring " +
71
+ "'#{ local_file }' to '#{ ip }'."
72
+ ftp.put(
73
+ File.join(local_path, local_file),
74
+ File.join(remote_path, remote_file)
75
+ )
76
+ end
77
+ end
78
+ end
79
+
80
+ ##
81
+ # Removes the transferred archive file(s) from the storage location.
82
+ # Any error raised will be rescued during Cycling
83
+ # and a warning will be logged, containing the error message.
84
+ def remove!(package)
85
+ remote_path = remote_path_for(package)
86
+
87
+ connection do |ftp|
88
+ transferred_files_for(package) do |local_file, remote_file|
89
+ Logger.message "#{storage_name} started removing " +
90
+ "'#{ local_file }' from '#{ ip }'."
91
+
92
+ ftp.delete(File.join(remote_path, remote_file))
93
+ end
94
+
95
+ ftp.rmdir(remote_path)
96
+ end
97
+ end
98
+
99
+ ##
100
+ # Creates (if they don't exist yet) all the directories on the remote
101
+ # server in order to upload the backup file. Net::FTP does not support
102
+ # paths to directories that don't yet exist when creating new
103
+ # directories. Instead, we split the parts up in to an array (for each
104
+ # '/') and loop through that to create the directories one by one.
105
+ # Net::FTP raises an exception when the directory it's trying to create
106
+ # already exists, so we have rescue it
107
+ def create_remote_path(remote_path, ftp)
108
+ path_parts = Array.new
109
+ remote_path.split('/').each do |path_part|
110
+ path_parts << path_part
111
+ begin
112
+ ftp.mkdir(path_parts.join('/'))
113
+ rescue Net::FTPPermError; end
114
+ end
115
+ end
116
+
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,82 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Storage
5
+ class Local < Base
6
+
7
+ ##
8
+ # Path where the backup will be stored.
9
+ attr_accessor :path
10
+
11
+ ##
12
+ # Creates a new instance of the storage object
13
+ def initialize(model, storage_id = nil, &block)
14
+ super(model, storage_id)
15
+
16
+ @path ||= File.join(
17
+ File.expand_path(ENV['HOME'] || ''),
18
+ 'backups'
19
+ )
20
+
21
+ instance_eval(&block) if block_given?
22
+
23
+ @path = File.expand_path(@path)
24
+ end
25
+
26
+ private
27
+
28
+ ##
29
+ # Transfers the archived file to the specified path
30
+ def transfer!
31
+ remote_path = remote_path_for(@package)
32
+ FileUtils.mkdir_p(remote_path)
33
+
34
+ files_to_transfer_for(@package) do |local_file, remote_file|
35
+ Logger.message "#{storage_name} started transferring '#{ local_file }'."
36
+
37
+ src_path = File.join(local_path, local_file)
38
+ dst_path = File.join(remote_path, remote_file)
39
+ FileUtils.send(transfer_method, src_path, dst_path)
40
+ end
41
+ end
42
+
43
+ ##
44
+ # Removes the transferred archive file(s) from the storage location.
45
+ # Any error raised will be rescued during Cycling
46
+ # and a warning will be logged, containing the error message.
47
+ def remove!(package)
48
+ remote_path = remote_path_for(package)
49
+
50
+ messages = []
51
+ transferred_files_for(package) do |local_file, remote_file|
52
+ messages << "#{storage_name} started removing '#{ local_file }'."
53
+ end
54
+ Logger.message messages.join("\n")
55
+
56
+ FileUtils.rm_r(remote_path)
57
+ end
58
+
59
+ ##
60
+ # Set and return the transfer method.
61
+ # If this Local Storage is not the last Storage for the Model,
62
+ # force the transfer to use a *copy* operation and issue a warning.
63
+ def transfer_method
64
+ return @transfer_method if @transfer_method
65
+
66
+ if self == @model.storages.last
67
+ @transfer_method = :mv
68
+ else
69
+ Logger.warn Errors::Storage::Local::TransferError.new(<<-EOS)
70
+ Local File Copy Warning!
71
+ The final backup file(s) for '#{@model.label}' (#{@model.trigger})
72
+ will be *copied* to '#{remote_path_for(@package)}'
73
+ To avoid this, when using more than one Storage, the 'Local' Storage
74
+ should be added *last* so the files may be *moved* to their destination.
75
+ EOS
76
+ @transfer_method = :cp
77
+ end
78
+ end
79
+
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,116 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Only load the Fog gem when the Backup::Storage::Ninefold class is loaded
5
+ Backup::Dependency.load('fog')
6
+
7
+ module Backup
8
+ module Storage
9
+ class Ninefold < Base
10
+
11
+ ##
12
+ # Ninefold Credentials
13
+ attr_accessor :storage_token, :storage_secret
14
+
15
+ ##
16
+ # Ninefold directory path
17
+ attr_accessor :path
18
+
19
+ ##
20
+ # Creates a new instance of the storage object
21
+ def initialize(model, storage_id = nil, &block)
22
+ super(model, storage_id)
23
+
24
+ @path ||= 'backups'
25
+
26
+ instance_eval(&block) if block_given?
27
+ end
28
+
29
+
30
+ private
31
+
32
+ ##
33
+ # This is the provider that Fog uses for the Ninefold storage
34
+ def provider
35
+ 'Ninefold'
36
+ end
37
+
38
+ ##
39
+ # Establishes a connection to Amazon S3
40
+ def connection
41
+ @connection ||= Fog::Storage.new(
42
+ :provider => provider,
43
+ :ninefold_storage_token => storage_token,
44
+ :ninefold_storage_secret => storage_secret
45
+ )
46
+ end
47
+
48
+ ##
49
+ # Queries the connection for the directory for the given +remote_path+
50
+ # Returns nil if not found, or creates the directory if +create+ is true.
51
+ def directory_for(remote_path, create = false)
52
+ directory = connection.directories.get(remote_path)
53
+ if directory.nil? && create
54
+ directory = connection.directories.create(:key => remote_path)
55
+ end
56
+ directory
57
+ end
58
+
59
+ def remote_path_for(package)
60
+ super(package).sub(/^\//, '')
61
+ end
62
+
63
+ ##
64
+ # Transfers the archived file to the specified directory
65
+ def transfer!
66
+ remote_path = remote_path_for(@package)
67
+
68
+ directory = directory_for(remote_path, true)
69
+
70
+ files_to_transfer_for(@package) do |local_file, remote_file|
71
+ Logger.message "#{storage_name} started transferring '#{ local_file }'."
72
+
73
+ File.open(File.join(local_path, local_file), 'r') do |file|
74
+ directory.files.create(:key => remote_file, :body => file)
75
+ end
76
+ end
77
+ end
78
+
79
+ ##
80
+ # Removes the transferred archive file(s) from the storage location.
81
+ # Any error raised will be rescued during Cycling
82
+ # and a warning will be logged, containing the error message.
83
+ def remove!(package)
84
+ remote_path = remote_path_for(package)
85
+
86
+ if directory = directory_for(remote_path)
87
+ not_found = []
88
+
89
+ transferred_files_for(package) do |local_file, remote_file|
90
+ Logger.message "#{storage_name} started removing " +
91
+ "'#{ local_file }' from Ninefold."
92
+
93
+ if file = directory.files.get(remote_file)
94
+ file.destroy
95
+ else
96
+ not_found << remote_file
97
+ end
98
+ end
99
+
100
+ directory.destroy
101
+
102
+ unless not_found.empty?
103
+ raise Errors::Storage::Ninefold::NotFoundError, <<-EOS
104
+ The following file(s) were not found in '#{ remote_path }'
105
+ #{ not_found.join("\n") }
106
+ EOS
107
+ end
108
+ else
109
+ raise Errors::Storage::Ninefold::NotFoundError,
110
+ "Directory at '#{remote_path}' not found"
111
+ end
112
+ end
113
+
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,149 @@
1
+ # encoding: utf-8
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
+ module Backup
8
+ module Storage
9
+ class RSync < Base
10
+ include Backup::CLI::Helpers
11
+
12
+ ##
13
+ # Server credentials
14
+ attr_accessor :username, :password
15
+
16
+ ##
17
+ # Server IP Address and SSH port
18
+ attr_accessor :ip, :port
19
+
20
+ ##
21
+ # Path to store backups to
22
+ attr_accessor :path
23
+
24
+ ##
25
+ # Flag to use local backups
26
+ attr_accessor :local
27
+
28
+ ##
29
+ # Creates a new instance of the storage object
30
+ def initialize(model, storage_id = nil, &block)
31
+ super(model, storage_id)
32
+
33
+ @port ||= 22
34
+ @path ||= 'backups'
35
+ @local ||= false
36
+
37
+ instance_eval(&block) if block_given?
38
+
39
+ @path = path.sub(/^\~\//, '')
40
+ end
41
+
42
+ private
43
+
44
+ ##
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
51
+
52
+ ##
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 }
58
+ end
59
+
60
+ ##
61
+ # Transfers the archived file to the specified remote server
62
+ def transfer!
63
+ write_password_file! unless local
64
+
65
+ remote_path = remote_path_for(@package)
66
+
67
+ create_remote_path!(remote_path)
68
+
69
+ files_to_transfer_for(@package) do |local_file, remote_file|
70
+ if local
71
+ Logger.message "#{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.message "#{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
86
+ end
87
+
88
+ ensure
89
+ remove_password_file! unless local
90
+ end
91
+
92
+ ##
93
+ # Note: Storage::RSync doesn't cycle
94
+ def remove!; end
95
+
96
+ ##
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 }'")
105
+ end
106
+ end
107
+ end
108
+
109
+ ##
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
117
+ end
118
+ end
119
+
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
126
+ end
127
+
128
+ ##
129
+ # Returns Rsync syntax for using a password file
130
+ def rsync_password_file
131
+ "--password-file='#{@password_file.path}'" if @password_file
132
+ end
133
+
134
+ ##
135
+ # Returns Rsync syntax for defining a port to connect to
136
+ def rsync_port
137
+ "-e 'ssh -p #{port}'"
138
+ end
139
+
140
+ ##
141
+ # RSync options
142
+ # -z = Compresses the bytes that will be transferred to reduce bandwidth usage
143
+ def rsync_options
144
+ "-z"
145
+ end
146
+
147
+ end
148
+ end
149
+ end