dmitryv-backup 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/CHANGELOG +125 -0
  2. data/LICENSE +20 -0
  3. data/README.md +180 -0
  4. data/VERSION +1 -0
  5. data/bin/backup +108 -0
  6. data/generators/backup/backup_generator.rb +69 -0
  7. data/generators/backup/templates/backup.rake +56 -0
  8. data/generators/backup/templates/backup.rb +229 -0
  9. data/generators/backup/templates/create_backup_tables.rb +18 -0
  10. data/generators/backup_update/backup_update_generator.rb +50 -0
  11. data/generators/backup_update/templates/migrations/update_backup_tables.rb +27 -0
  12. data/lib/backup.rb +131 -0
  13. data/lib/backup/adapters/archive.rb +34 -0
  14. data/lib/backup/adapters/base.rb +138 -0
  15. data/lib/backup/adapters/custom.rb +41 -0
  16. data/lib/backup/adapters/mysql.rb +60 -0
  17. data/lib/backup/adapters/postgresql.rb +56 -0
  18. data/lib/backup/adapters/sqlite.rb +25 -0
  19. data/lib/backup/command_helper.rb +11 -0
  20. data/lib/backup/compressors/base.rb +7 -0
  21. data/lib/backup/compressors/gzip.rb +9 -0
  22. data/lib/backup/compressors/seven_zip.rb +9 -0
  23. data/lib/backup/configuration/adapter.rb +21 -0
  24. data/lib/backup/configuration/adapter_options.rb +8 -0
  25. data/lib/backup/configuration/attributes.rb +19 -0
  26. data/lib/backup/configuration/base.rb +77 -0
  27. data/lib/backup/configuration/helpers.rb +24 -0
  28. data/lib/backup/configuration/mail.rb +20 -0
  29. data/lib/backup/configuration/smtp.rb +8 -0
  30. data/lib/backup/configuration/storage.rb +8 -0
  31. data/lib/backup/connection/cloudfiles.rb +75 -0
  32. data/lib/backup/connection/s3.rb +85 -0
  33. data/lib/backup/environment/base.rb +12 -0
  34. data/lib/backup/environment/rails_configuration.rb +15 -0
  35. data/lib/backup/environment/unix_configuration.rb +109 -0
  36. data/lib/backup/mail/base.rb +97 -0
  37. data/lib/backup/mail/mail.txt +7 -0
  38. data/lib/backup/record/base.rb +65 -0
  39. data/lib/backup/record/cloudfiles.rb +28 -0
  40. data/lib/backup/record/ftp.rb +39 -0
  41. data/lib/backup/record/local.rb +26 -0
  42. data/lib/backup/record/s3.rb +26 -0
  43. data/lib/backup/record/scp.rb +33 -0
  44. data/lib/backup/record/sftp.rb +38 -0
  45. data/lib/backup/storage/base.rb +10 -0
  46. data/lib/backup/storage/cloudfiles.rb +16 -0
  47. data/lib/backup/storage/ftp.rb +38 -0
  48. data/lib/backup/storage/local.rb +22 -0
  49. data/lib/backup/storage/s3.rb +17 -0
  50. data/lib/backup/storage/scp.rb +30 -0
  51. data/lib/backup/storage/sftp.rb +31 -0
  52. data/lib/generators/backup/USAGE +10 -0
  53. data/lib/generators/backup/backup_generator.rb +47 -0
  54. data/lib/generators/backup/templates/backup.rake +56 -0
  55. data/lib/generators/backup/templates/backup.rb +229 -0
  56. data/lib/generators/backup/templates/create_backup_tables.rb +18 -0
  57. data/setup/backup.rb +231 -0
  58. data/setup/backup.sqlite3 +0 -0
  59. metadata +271 -0
@@ -0,0 +1,7 @@
1
+ A backup was successfully created for the trigger: ":trigger"!
2
+
3
+ The backup was created on ":day of :month :year at :time", using the ":adapter" adapter.
4
+
5
+ The Backup was stored in ":location" :remote.
6
+
7
+ The following backup was stored: ":backup"
@@ -0,0 +1,65 @@
1
+ module Backup
2
+ module Record
3
+ class Base < ActiveRecord::Base
4
+
5
+ if DB_CONNECTION_SETTINGS
6
+ establish_connection(DB_CONNECTION_SETTINGS)
7
+ end
8
+
9
+ set_table_name 'backup'
10
+
11
+ default_scope :order => 'created_at desc'
12
+
13
+ # Callbacks
14
+ after_save :clean_backups
15
+
16
+ # Attributes
17
+ attr_accessor :adapter_config, :keep_backups
18
+
19
+ # Receives the options hash and stores it
20
+ def load_adapter(adapter)
21
+ self.adapter_config = adapter
22
+ self.trigger = adapter.procedure.trigger
23
+ self.adapter = adapter.procedure.adapter_name.to_s
24
+ self.filename = adapter.final_file
25
+ self.keep_backups = adapter.procedure.attributes['keep_backups']
26
+
27
+ # TODO calculate md5sum of file
28
+ load_specific_settings(adapter) if respond_to?(:load_specific_settings)
29
+ end
30
+
31
+ # Destroys all backups for the specified trigger from Remote Server (FTP)
32
+ def self.destroy_all_backups(procedure, trigger)
33
+ backups = self.all(:conditions => {:trigger => trigger})
34
+ unless backups.empty?
35
+ # Derived classes must implement this method!
36
+ self.destroy_backups(procedure, backups)
37
+
38
+ puts "\nAll \"#{procedure.trigger}\" backups destroyed.\n\n"
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ # Maintains the backup file amount on the remote server
45
+ # This is invoked after a successful record save
46
+ # This deletes the oldest files when the backup limit has been exceeded
47
+ def clean_backups
48
+ if keep_backups.is_a?(Integer)
49
+ backups = self.class.all(:conditions => {:trigger => trigger})
50
+ backups_to_destroy = backups[keep_backups, backups.size] || []
51
+
52
+ unless backups_to_destroy.empty?
53
+ # Derived classes must implement this method!
54
+ self.class.destroy_backups(adapter_config.procedure, backups_to_destroy)
55
+
56
+ puts "\nBackup storage for \"#{trigger}\" is limited to #{keep_backups} backups."
57
+ puts "\nThe #{keep_backups} most recent backups are now stored on the remote server.\n\n"
58
+ end
59
+ end
60
+ end
61
+
62
+ end
63
+ end
64
+ end
65
+
@@ -0,0 +1,28 @@
1
+ require 'backup/connection/cloudfiles'
2
+
3
+ module Backup
4
+ module Record
5
+ class CloudFiles < Backup::Record::Base
6
+
7
+ alias_attribute :container, :bucket
8
+
9
+ def load_specific_settings(adapter)
10
+ self.container = adapter.procedure.get_storage_configuration.attributes['container']
11
+ end
12
+
13
+ private
14
+
15
+ def self.destroy_backups(procedure, backups)
16
+ cf = Backup::Connection::CloudFiles.new
17
+ cf.static_initialize(procedure)
18
+ cf.connect
19
+ backups.each do |backup|
20
+ puts "\nDestroying backup \"#{backup.filename}\" from container \"#{backup.container}\"."
21
+ cf.destroy(backup.filename, backup.container)
22
+ backup.destroy
23
+ end
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,39 @@
1
+ require 'net/ftp'
2
+
3
+ module Backup
4
+ module Record
5
+ class FTP < Backup::Record::Base
6
+
7
+ attr_accessor :ip, :user, :password
8
+
9
+ def load_specific_settings(adapter)
10
+ %w(ip user password path).each do |method|
11
+ send(:"#{method}=", adapter.procedure.get_storage_configuration.attributes[method])
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def self.destroy_backups(procedure, backups)
18
+ ip = procedure.get_storage_configuration.attributes['ip']
19
+ user = procedure.get_storage_configuration.attributes['user']
20
+ password = procedure.get_storage_configuration.attributes['password']
21
+
22
+ Net::FTP.open(ip, user, password) do |ftp|
23
+ backups.each do |backup|
24
+ puts "\nDestroying backup \"#{backup.filename}\" from path \"#{backup.path}\"."
25
+ begin
26
+ ftp.chdir(backup.path)
27
+ ftp.delete(backup.filename)
28
+ backup.destroy
29
+ rescue
30
+ puts "Could not find backup #{backup.path}/#{backup.filename}."
31
+ backup.destroy
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,26 @@
1
+ module Backup
2
+ module Record
3
+ class Local < Backup::Record::Base
4
+
5
+ def load_specific_settings(adapter)
6
+ self.path = adapter.procedure.get_storage_configuration.attributes['path']
7
+ end
8
+
9
+ private
10
+
11
+ class << self
12
+ include Backup::CommandHelper
13
+
14
+ def destroy_backups(procedure, backups)
15
+ backups.each do |backup|
16
+ puts "\nDestroying backup \"#{backup.filename}\" from path \"#{backup.path}\"."
17
+ run "rm #{File.join(backup.path, backup.filename)}"
18
+ backup.destroy
19
+ end
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+
@@ -0,0 +1,26 @@
1
+ require 'backup/connection/s3'
2
+
3
+ module Backup
4
+ module Record
5
+ class S3 < Backup::Record::Base
6
+
7
+ def load_specific_settings(adapter)
8
+ self.bucket = adapter.procedure.get_storage_configuration.attributes['bucket']
9
+ end
10
+
11
+ private
12
+
13
+ def self.destroy_backups(procedure, backups)
14
+ s3 = Backup::Connection::S3.new
15
+ s3.static_initialize(procedure)
16
+ s3.connect
17
+ backups.each do |backup|
18
+ puts "\nDestroying backup \"#{backup.filename}\" from bucket \"#{backup.bucket}\"."
19
+ s3.destroy(backup.filename, backup.bucket)
20
+ backup.destroy
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,33 @@
1
+ require 'net/scp'
2
+
3
+ module Backup
4
+ module Record
5
+ class SCP < Backup::Record::Base
6
+
7
+ attr_accessor :ip, :user, :password
8
+
9
+ def load_specific_settings(adapter)
10
+ %w(ip user password path).each do |method|
11
+ send(:"#{method}=", adapter.procedure.get_storage_configuration.attributes[method])
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def self.destroy_backups(procedure, backups)
18
+ ip = procedure.get_storage_configuration.attributes['ip']
19
+ user = procedure.get_storage_configuration.attributes['user']
20
+ password = procedure.get_storage_configuration.attributes['password']
21
+
22
+ Net::SSH.start(ip, user, :password => password) do |ssh|
23
+ backups.each do |backup|
24
+ puts "\nDestroying backup \"#{backup.filename}\" from path \"#{backup.path}\"."
25
+ ssh.exec("rm #{File.join(backup.path, backup.filename)}")
26
+ backup.destroy
27
+ end
28
+ end
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,38 @@
1
+ require 'net/sftp'
2
+
3
+ module Backup
4
+ module Record
5
+ class SFTP < Backup::Record::Base
6
+
7
+ attr_accessor :ip, :user, :password
8
+
9
+ def load_specific_settings(adapter)
10
+ %w(ip user password path).each do |method|
11
+ send(:"#{method}=", adapter.procedure.get_storage_configuration.attributes[method])
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def self.destroy_backups(procedure, backups)
18
+ ip = procedure.get_storage_configuration.attributes['ip']
19
+ user = procedure.get_storage_configuration.attributes['user']
20
+ password = procedure.get_storage_configuration.attributes['password']
21
+
22
+ Net::SFTP.start(ip, user, :password => password) do |sftp|
23
+ backups.each do |backup|
24
+ puts "\nDestroying backup \"#{backup.filename}\" from path \"#{backup.path}\"."
25
+ begin
26
+ sftp.remove!(File.join(backup.path, backup.filename))
27
+ backup.destroy
28
+ rescue
29
+ puts "Could not find backup #{backup.path}/#{backup.filename}.."
30
+ backup.destroy
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,10 @@
1
+ module Backup
2
+ module Storage
3
+ class Base
4
+ include Backup::CommandHelper
5
+
6
+ end
7
+ end
8
+ end
9
+
10
+
@@ -0,0 +1,16 @@
1
+ require 'backup/connection/cloudfiles'
2
+
3
+ module Backup
4
+ module Storage
5
+ class CloudFiles < Base
6
+
7
+ # Stores the backup file on the remote server using Rackspace Cloud Files
8
+ def initialize(adapter)
9
+ cf = Backup::Connection::CloudFiles.new(adapter)
10
+ cf.connect
11
+ cf.store
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,38 @@
1
+ require 'net/ftp'
2
+
3
+ module Backup
4
+ module Storage
5
+ class FTP < Backup::Storage::Base
6
+
7
+ attr_accessor :user, :password, :ip, :path, :tmp_path, :final_file
8
+
9
+ # Stores the backup file on the remote server using FTP
10
+ def initialize(adapter)
11
+ %w(ip user password path).each do |method|
12
+ send("#{method}=", adapter.procedure.get_storage_configuration.attributes[method])
13
+ end
14
+
15
+ final_file = adapter.final_file
16
+ tmp_path = adapter.tmp_path
17
+
18
+ Net::FTP.open(ip, user, password) do |ftp|
19
+ begin
20
+ ftp.chdir(path)
21
+ rescue
22
+ puts "Could not find or access \"#{path}\" on \"#{ip}\", please ensure this directory exists and is accessible by the user \"#{user}\"."
23
+ exit
24
+ end
25
+
26
+ begin
27
+ puts "Storing \"#{final_file}\" to path \"#{path}\" on remote server (#{ip})."
28
+ ftp.putbinaryfile(File.join(tmp_path, final_file).gsub('\ ', ' '), File.join(path, final_file))
29
+ rescue
30
+ puts "Could not save file to backup server. Is the \"#{path}\" directory writable?"
31
+ exit
32
+ end
33
+ end
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,22 @@
1
+ module Backup
2
+ module Storage
3
+ class Local < Base
4
+
5
+ # Store on same machine, preferentially in a different hard drive or in
6
+ # a mounted network path (NFS, Samba, etc)
7
+ attr_accessor :path, :tmp_path, :final_file
8
+
9
+ # Stores the backup file on local machine
10
+ def initialize(adapter)
11
+ self.path = adapter.procedure.get_storage_configuration.attributes['path']
12
+ self.tmp_path = adapter.tmp_path
13
+ self.final_file = adapter.final_file
14
+
15
+ run "mkdir -p #{path}"
16
+ run "cp #{File.join(tmp_path, final_file).gsub('\ ', ' ')} #{File.join(path, final_file)}"
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,17 @@
1
+ require 'backup/connection/s3'
2
+
3
+ module Backup
4
+ module Storage
5
+ class S3 < Base
6
+
7
+ # Stores the backup file on the remote server using S3
8
+ def initialize(adapter)
9
+ s3 = Backup::Connection::S3.new(adapter)
10
+ s3.connect
11
+ log("Saving '#{s3.final_file}' to s3 bucket '#{s3.s3_bucket}'")
12
+ s3.store
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,30 @@
1
+ require 'net/scp'
2
+
3
+ module Backup
4
+ module Storage
5
+ class SCP < Base
6
+
7
+ attr_accessor :user, :password, :ip, :path, :tmp_path, :final_file
8
+
9
+ # Stores the backup file on the remote server using SCP
10
+ def initialize(adapter)
11
+ %w(ip user password path).each do |method|
12
+ send("#{method}=", adapter.procedure.get_storage_configuration.attributes[method])
13
+ end
14
+
15
+ final_file = adapter.final_file
16
+ tmp_path = adapter.tmp_path
17
+
18
+ Net::SSH.start(ip, user, :password => password) do |ssh|
19
+ ssh.exec "mkdir -p #{path}"
20
+ end
21
+
22
+ puts "Storing \"#{final_file}\" to path \"#{path}\" on remote server (#{ip})."
23
+ Net::SCP.start(ip, user, :password => password) do |scp|
24
+ scp.upload! File.join(tmp_path, final_file).gsub('\ ', ' '), path
25
+ end
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,31 @@
1
+ require 'net/sftp'
2
+
3
+ module Backup
4
+ module Storage
5
+ class SFTP < Base
6
+
7
+ attr_accessor :user, :password, :ip, :path, :tmp_path, :final_file
8
+
9
+ # Stores the backup file on the remote server using SFTP
10
+ def initialize(adapter)
11
+ %w(ip user password path).each do |method|
12
+ send("#{method}=", adapter.procedure.get_storage_configuration.attributes[method])
13
+ end
14
+
15
+ final_file = adapter.final_file
16
+ tmp_path = adapter.tmp_path
17
+
18
+ Net::SFTP.start(ip, user, :password => password) do |sftp|
19
+ begin
20
+ puts "Storing \"#{final_file}\" to path \"#{path}\" on remote server (#{ip})."
21
+ sftp.upload!(File.join(tmp_path, final_file).gsub('\ ', ' '), File.join(path, final_file))
22
+ rescue
23
+ puts "Could not find \"#{path}\" on \"#{ip}\", please ensure this directory exists."
24
+ exit
25
+ end
26
+ end
27
+ end
28
+
29
+ end
30
+ end
31
+ end