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.
- data/.gitignore +7 -0
- data/.travis.yml +10 -0
- data/Gemfile +28 -0
- data/Gemfile.lock +130 -0
- data/Guardfile +21 -0
- data/LICENSE.md +24 -0
- data/README.md +476 -0
- data/backup_checksum.gemspec +32 -0
- data/bin/backup +11 -0
- data/lib/backup.rb +217 -0
- data/lib/backup/archive.rb +117 -0
- data/lib/backup/binder.rb +22 -0
- data/lib/backup/checksum/base.rb +44 -0
- data/lib/backup/checksum/shasum.rb +16 -0
- data/lib/backup/cleaner.rb +121 -0
- data/lib/backup/cli/helpers.rb +88 -0
- data/lib/backup/cli/utility.rb +247 -0
- data/lib/backup/compressor/base.rb +29 -0
- data/lib/backup/compressor/bzip2.rb +50 -0
- data/lib/backup/compressor/gzip.rb +47 -0
- data/lib/backup/compressor/lzma.rb +50 -0
- data/lib/backup/compressor/pbzip2.rb +56 -0
- data/lib/backup/config.rb +173 -0
- data/lib/backup/configuration/base.rb +15 -0
- data/lib/backup/configuration/checksum/base.rb +9 -0
- data/lib/backup/configuration/checksum/shasum.rb +9 -0
- data/lib/backup/configuration/compressor/base.rb +9 -0
- data/lib/backup/configuration/compressor/bzip2.rb +23 -0
- data/lib/backup/configuration/compressor/gzip.rb +23 -0
- data/lib/backup/configuration/compressor/lzma.rb +23 -0
- data/lib/backup/configuration/compressor/pbzip2.rb +28 -0
- data/lib/backup/configuration/database/base.rb +19 -0
- data/lib/backup/configuration/database/mongodb.rb +49 -0
- data/lib/backup/configuration/database/mysql.rb +42 -0
- data/lib/backup/configuration/database/postgresql.rb +41 -0
- data/lib/backup/configuration/database/redis.rb +39 -0
- data/lib/backup/configuration/database/riak.rb +29 -0
- data/lib/backup/configuration/encryptor/base.rb +9 -0
- data/lib/backup/configuration/encryptor/gpg.rb +17 -0
- data/lib/backup/configuration/encryptor/open_ssl.rb +32 -0
- data/lib/backup/configuration/helpers.rb +52 -0
- data/lib/backup/configuration/notifier/base.rb +28 -0
- data/lib/backup/configuration/notifier/campfire.rb +25 -0
- data/lib/backup/configuration/notifier/hipchat.rb +41 -0
- data/lib/backup/configuration/notifier/mail.rb +112 -0
- data/lib/backup/configuration/notifier/presently.rb +25 -0
- data/lib/backup/configuration/notifier/prowl.rb +23 -0
- data/lib/backup/configuration/notifier/twitter.rb +21 -0
- data/lib/backup/configuration/storage/base.rb +18 -0
- data/lib/backup/configuration/storage/cloudfiles.rb +25 -0
- data/lib/backup/configuration/storage/dropbox.rb +58 -0
- data/lib/backup/configuration/storage/ftp.rb +29 -0
- data/lib/backup/configuration/storage/local.rb +17 -0
- data/lib/backup/configuration/storage/ninefold.rb +20 -0
- data/lib/backup/configuration/storage/rsync.rb +29 -0
- data/lib/backup/configuration/storage/s3.rb +25 -0
- data/lib/backup/configuration/storage/scp.rb +25 -0
- data/lib/backup/configuration/storage/sftp.rb +25 -0
- data/lib/backup/configuration/syncer/base.rb +10 -0
- data/lib/backup/configuration/syncer/cloud.rb +23 -0
- data/lib/backup/configuration/syncer/cloud_files.rb +30 -0
- data/lib/backup/configuration/syncer/rsync/base.rb +28 -0
- data/lib/backup/configuration/syncer/rsync/local.rb +11 -0
- data/lib/backup/configuration/syncer/rsync/pull.rb +11 -0
- data/lib/backup/configuration/syncer/rsync/push.rb +31 -0
- data/lib/backup/configuration/syncer/s3.rb +23 -0
- data/lib/backup/database/base.rb +59 -0
- data/lib/backup/database/mongodb.rb +232 -0
- data/lib/backup/database/mysql.rb +163 -0
- data/lib/backup/database/postgresql.rb +146 -0
- data/lib/backup/database/redis.rb +139 -0
- data/lib/backup/database/riak.rb +69 -0
- data/lib/backup/dependency.rb +114 -0
- data/lib/backup/encryptor/base.rb +29 -0
- data/lib/backup/encryptor/gpg.rb +80 -0
- data/lib/backup/encryptor/open_ssl.rb +72 -0
- data/lib/backup/errors.rb +124 -0
- data/lib/backup/logger.rb +152 -0
- data/lib/backup/model.rb +386 -0
- data/lib/backup/notifier/base.rb +81 -0
- data/lib/backup/notifier/campfire.rb +168 -0
- data/lib/backup/notifier/hipchat.rb +99 -0
- data/lib/backup/notifier/mail.rb +206 -0
- data/lib/backup/notifier/presently.rb +88 -0
- data/lib/backup/notifier/prowl.rb +65 -0
- data/lib/backup/notifier/twitter.rb +70 -0
- data/lib/backup/package.rb +51 -0
- data/lib/backup/packager.rb +108 -0
- data/lib/backup/pipeline.rb +107 -0
- data/lib/backup/splitter.rb +75 -0
- data/lib/backup/storage/base.rb +119 -0
- data/lib/backup/storage/cloudfiles.rb +87 -0
- data/lib/backup/storage/cycler.rb +117 -0
- data/lib/backup/storage/dropbox.rb +181 -0
- data/lib/backup/storage/ftp.rb +119 -0
- data/lib/backup/storage/local.rb +82 -0
- data/lib/backup/storage/ninefold.rb +116 -0
- data/lib/backup/storage/rsync.rb +149 -0
- data/lib/backup/storage/s3.rb +94 -0
- data/lib/backup/storage/scp.rb +99 -0
- data/lib/backup/storage/sftp.rb +108 -0
- data/lib/backup/syncer/base.rb +42 -0
- data/lib/backup/syncer/cloud.rb +190 -0
- data/lib/backup/syncer/cloud_files.rb +56 -0
- data/lib/backup/syncer/rsync/base.rb +52 -0
- data/lib/backup/syncer/rsync/local.rb +53 -0
- data/lib/backup/syncer/rsync/pull.rb +38 -0
- data/lib/backup/syncer/rsync/push.rb +113 -0
- data/lib/backup/syncer/s3.rb +47 -0
- data/lib/backup/template.rb +46 -0
- data/lib/backup/version.rb +43 -0
- data/spec/archive_spec.rb +335 -0
- data/spec/cleaner_spec.rb +304 -0
- data/spec/cli/helpers_spec.rb +176 -0
- data/spec/cli/utility_spec.rb +363 -0
- data/spec/compressor/base_spec.rb +31 -0
- data/spec/compressor/bzip2_spec.rb +83 -0
- data/spec/compressor/gzip_spec.rb +83 -0
- data/spec/compressor/lzma_spec.rb +83 -0
- data/spec/compressor/pbzip2_spec.rb +124 -0
- data/spec/config_spec.rb +321 -0
- data/spec/configuration/base_spec.rb +35 -0
- data/spec/configuration/compressor/bzip2_spec.rb +29 -0
- data/spec/configuration/compressor/gzip_spec.rb +29 -0
- data/spec/configuration/compressor/lzma_spec.rb +29 -0
- data/spec/configuration/compressor/pbzip2_spec.rb +32 -0
- data/spec/configuration/database/base_spec.rb +17 -0
- data/spec/configuration/database/mongodb_spec.rb +56 -0
- data/spec/configuration/database/mysql_spec.rb +53 -0
- data/spec/configuration/database/postgresql_spec.rb +53 -0
- data/spec/configuration/database/redis_spec.rb +50 -0
- data/spec/configuration/database/riak_spec.rb +35 -0
- data/spec/configuration/encryptor/gpg_spec.rb +26 -0
- data/spec/configuration/encryptor/open_ssl_spec.rb +35 -0
- data/spec/configuration/notifier/base_spec.rb +32 -0
- data/spec/configuration/notifier/campfire_spec.rb +32 -0
- data/spec/configuration/notifier/hipchat_spec.rb +44 -0
- data/spec/configuration/notifier/mail_spec.rb +71 -0
- data/spec/configuration/notifier/presently_spec.rb +35 -0
- data/spec/configuration/notifier/prowl_spec.rb +29 -0
- data/spec/configuration/notifier/twitter_spec.rb +35 -0
- data/spec/configuration/storage/cloudfiles_spec.rb +41 -0
- data/spec/configuration/storage/dropbox_spec.rb +38 -0
- data/spec/configuration/storage/ftp_spec.rb +44 -0
- data/spec/configuration/storage/local_spec.rb +29 -0
- data/spec/configuration/storage/ninefold_spec.rb +32 -0
- data/spec/configuration/storage/rsync_spec.rb +41 -0
- data/spec/configuration/storage/s3_spec.rb +38 -0
- data/spec/configuration/storage/scp_spec.rb +41 -0
- data/spec/configuration/storage/sftp_spec.rb +41 -0
- data/spec/configuration/syncer/cloud_files_spec.rb +44 -0
- data/spec/configuration/syncer/rsync/base_spec.rb +33 -0
- data/spec/configuration/syncer/rsync/local_spec.rb +10 -0
- data/spec/configuration/syncer/rsync/pull_spec.rb +10 -0
- data/spec/configuration/syncer/rsync/push_spec.rb +43 -0
- data/spec/configuration/syncer/s3_spec.rb +38 -0
- data/spec/database/base_spec.rb +54 -0
- data/spec/database/mongodb_spec.rb +428 -0
- data/spec/database/mysql_spec.rb +335 -0
- data/spec/database/postgresql_spec.rb +278 -0
- data/spec/database/redis_spec.rb +260 -0
- data/spec/database/riak_spec.rb +108 -0
- data/spec/dependency_spec.rb +49 -0
- data/spec/encryptor/base_spec.rb +30 -0
- data/spec/encryptor/gpg_spec.rb +134 -0
- data/spec/encryptor/open_ssl_spec.rb +129 -0
- data/spec/errors_spec.rb +306 -0
- data/spec/logger_spec.rb +363 -0
- data/spec/model_spec.rb +649 -0
- data/spec/notifier/base_spec.rb +89 -0
- data/spec/notifier/campfire_spec.rb +199 -0
- data/spec/notifier/hipchat_spec.rb +188 -0
- data/spec/notifier/mail_spec.rb +280 -0
- data/spec/notifier/presently_spec.rb +181 -0
- data/spec/notifier/prowl_spec.rb +117 -0
- data/spec/notifier/twitter_spec.rb +132 -0
- data/spec/package_spec.rb +61 -0
- data/spec/packager_spec.rb +225 -0
- data/spec/pipeline_spec.rb +257 -0
- data/spec/spec_helper.rb +59 -0
- data/spec/splitter_spec.rb +120 -0
- data/spec/storage/base_spec.rb +160 -0
- data/spec/storage/cloudfiles_spec.rb +230 -0
- data/spec/storage/cycler_spec.rb +239 -0
- data/spec/storage/dropbox_spec.rb +370 -0
- data/spec/storage/ftp_spec.rb +247 -0
- data/spec/storage/local_spec.rb +235 -0
- data/spec/storage/ninefold_spec.rb +319 -0
- data/spec/storage/rsync_spec.rb +345 -0
- data/spec/storage/s3_spec.rb +221 -0
- data/spec/storage/scp_spec.rb +209 -0
- data/spec/storage/sftp_spec.rb +220 -0
- data/spec/syncer/base_spec.rb +22 -0
- data/spec/syncer/cloud_files_spec.rb +192 -0
- data/spec/syncer/rsync/base_spec.rb +118 -0
- data/spec/syncer/rsync/local_spec.rb +121 -0
- data/spec/syncer/rsync/pull_spec.rb +90 -0
- data/spec/syncer/rsync/push_spec.rb +327 -0
- data/spec/syncer/s3_spec.rb +192 -0
- data/spec/version_spec.rb +21 -0
- data/templates/cli/utility/archive +25 -0
- data/templates/cli/utility/compressor/bzip2 +7 -0
- data/templates/cli/utility/compressor/gzip +7 -0
- data/templates/cli/utility/compressor/lzma +7 -0
- data/templates/cli/utility/compressor/pbzip2 +7 -0
- data/templates/cli/utility/config +31 -0
- data/templates/cli/utility/database/mongodb +18 -0
- data/templates/cli/utility/database/mysql +21 -0
- data/templates/cli/utility/database/postgresql +17 -0
- data/templates/cli/utility/database/redis +16 -0
- data/templates/cli/utility/database/riak +11 -0
- data/templates/cli/utility/encryptor/gpg +12 -0
- data/templates/cli/utility/encryptor/openssl +9 -0
- data/templates/cli/utility/model.erb +23 -0
- data/templates/cli/utility/notifier/campfire +12 -0
- data/templates/cli/utility/notifier/hipchat +15 -0
- data/templates/cli/utility/notifier/mail +22 -0
- data/templates/cli/utility/notifier/presently +13 -0
- data/templates/cli/utility/notifier/prowl +11 -0
- data/templates/cli/utility/notifier/twitter +13 -0
- data/templates/cli/utility/splitter +7 -0
- data/templates/cli/utility/storage/cloud_files +22 -0
- data/templates/cli/utility/storage/dropbox +20 -0
- data/templates/cli/utility/storage/ftp +12 -0
- data/templates/cli/utility/storage/local +7 -0
- data/templates/cli/utility/storage/ninefold +9 -0
- data/templates/cli/utility/storage/rsync +11 -0
- data/templates/cli/utility/storage/s3 +19 -0
- data/templates/cli/utility/storage/scp +11 -0
- data/templates/cli/utility/storage/sftp +11 -0
- data/templates/cli/utility/syncer/cloud_files +48 -0
- data/templates/cli/utility/syncer/rsync_local +12 -0
- data/templates/cli/utility/syncer/rsync_pull +17 -0
- data/templates/cli/utility/syncer/rsync_push +17 -0
- data/templates/cli/utility/syncer/s3 +45 -0
- data/templates/general/links +11 -0
- data/templates/general/version.erb +2 -0
- data/templates/notifier/mail/failure.erb +9 -0
- data/templates/notifier/mail/success.erb +7 -0
- data/templates/notifier/mail/warning.erb +9 -0
- data/templates/storage/dropbox/authorization_url.erb +6 -0
- data/templates/storage/dropbox/authorized.erb +4 -0
- data/templates/storage/dropbox/cache_file_written.erb +10 -0
- 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
|